为什么允许我在非静态构造函数中为静态只读字段对象定义 SendCompletedEventHandler?
Why am I allowed to define a SendCompletedEventHandler for a static read-only field object, inside a non-static constructor?
private static readonly SmtpClient SmtpClient = new SmtpClient (...)
public Constructor()
{
SmtpClient.SendCompleted += new SendCompletedEventHandler(SendCompletedMethod);
// Above is allowed and legal. Why, when the field is marked as static read-only?
}
知道为什么允许这样做吗?我真的很困惑。此外,如果构造函数被执行两次,这将产生错误。
字段是只读的,这意味着您不能更改字段 - 但由于SmtpClient
是引用类型,字段 只是引用。所以:您不能 更改引用 - 您 可以 ,但是,可以对对象 behind 引用,如果该类型是可变的,这显然是可变的。这与以下内容没有什么不同:
class Foo
{
public string Bar {get;set;}
}
static readonly Foo s_foo = new Foo();
//... later
s_foo.Bar = "we changed it";
将字段标记为 readonly
不会使编译器将基础类型视为不可变的(除非我们讨论的是具有不同规则的值类型)。它不能,因为任何方法(包括属性 getter,它们只是具有特定形状的方法)都可以在调用者不知情的情况下改变内部状态。
注意对于value-types,有readonly struct
的概念;在 那个 场景中,我们得到保证方法 不会 改变内部状态,这允许编译器和运行时更好地决定如何在值类型的字段上应用 readonly
(因此字段 是 的内容);如果没有 readonly struct
,编译器会在每次方法调用之前制作值类型的防御性副本,以防止字段更改;对于 readonly struct
,它不会,因为它相信类型不会改变。这是不是,但是,我说的是"switch to value-types";值类型用于非常特定的目的,在不了解所有影响的情况下不应随意使用它们。
private static readonly SmtpClient SmtpClient = new SmtpClient (...)
public Constructor()
{
SmtpClient.SendCompleted += new SendCompletedEventHandler(SendCompletedMethod);
// Above is allowed and legal. Why, when the field is marked as static read-only?
}
知道为什么允许这样做吗?我真的很困惑。此外,如果构造函数被执行两次,这将产生错误。
字段是只读的,这意味着您不能更改字段 - 但由于SmtpClient
是引用类型,字段 只是引用。所以:您不能 更改引用 - 您 可以 ,但是,可以对对象 behind 引用,如果该类型是可变的,这显然是可变的。这与以下内容没有什么不同:
class Foo
{
public string Bar {get;set;}
}
static readonly Foo s_foo = new Foo();
//... later
s_foo.Bar = "we changed it";
将字段标记为 readonly
不会使编译器将基础类型视为不可变的(除非我们讨论的是具有不同规则的值类型)。它不能,因为任何方法(包括属性 getter,它们只是具有特定形状的方法)都可以在调用者不知情的情况下改变内部状态。
注意对于value-types,有readonly struct
的概念;在 那个 场景中,我们得到保证方法 不会 改变内部状态,这允许编译器和运行时更好地决定如何在值类型的字段上应用 readonly
(因此字段 是 的内容);如果没有 readonly struct
,编译器会在每次方法调用之前制作值类型的防御性副本,以防止字段更改;对于 readonly struct
,它不会,因为它相信类型不会改变。这是不是,但是,我说的是"switch to value-types";值类型用于非常特定的目的,在不了解所有影响的情况下不应随意使用它们。