The field is read-only, which means you can't change the field - but since SmtpClient
is a reference type, the field is just the reference. So: you can't change the reference - you can, however, do whatever you want to the object behind the reference, if that type is mutable, which it clearly is. This is no different to:
class Foo
{
public string Bar {get;set;}
}
static readonly Foo s_foo = new Foo();
//... later
s_foo.Bar = "we changed it";
Marking a field as readonly
does not make the compiler treat the underlying type as immutable (unless we're talking about value-types, which have different rules). It can't, because any method (including property getters, which are just methods with a particular shape) could change the internal state without the caller knowing about it.
Note that for value-types, there is the concept of readonly struct
; in that scenario, we are given the guarantee that methods will not change the internal state, which allows the compiler and runtime to make better decisions about how to apply readonly
on fields that are value-types (and thus the field is the content); without readonly struct
, the compiler makes a defensive copy of the value-type before each method call, to prevent the field changing; with readonly struct
, it does not, as it trusts the type not to change. This is not, however, me saying "switch to value-types"; value-types are for very specific purposes, and they should not be used casually without understanding all the impact.
SmtpClient
reference though - you're only changing one of its fields. – Matthew Watson