【问题标题】:Why am I allowed to define a SendCompletedEventHandler for a static read-only field object, inside a non-static constructor?为什么允许我在非静态构造函数中为静态只读字段对象定义 SendCompletedEventHandler?
【发布时间】:2020-02-28 09:32:48
【问题描述】:
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 引用 - 您只是更改其中一个字段。

标签: c# .net-core constructor static smtpclient


【解决方案1】:

field 是只读的,这意味着您无法更改 field - 但由于 SmtpClient 是引用类型,field 只是参考。所以:您不能更改引用 - 但是,您可以对引用后面的对象做任何你想做的事情,如果该类型是可变的,它显然是。这与:

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,它不会,因为它相信类型不会改变。这不是不是,但是,我说的是“切换到值类型”;值类型用于非常特定的目的,在不了解所有影响的情况下不应随意使用它们。

【讨论】:

  • @LopDev:请不要编辑收缩;宫缩很好
  • 静态关键字是最令人困惑的。据我了解,我们不能在实例构造函数(非静态构造函数)中引用非静态字段?
  • @SpiritBob 您可以从实例构造函数访问任何内容;为什么你不能?
  • @SpiritBob 我不知道该说什么;总而言之“没有规则说你不能这样做” - 很难指出一个零规则列表来讨论它们......你能更具体地说明你在那里要求什么吗?
  • 想象一个班级Scholar。每个Scholars 都有相同的老师,因此,在Scholar 类中可以有一个static Teacher。当你对一位学者说告诉你的老师……时,这位学者知道这位老师是谁。如果你说老师告诉学者...,老师不知道你说的是哪个学者,甚至可能没有学者。
猜你喜欢
  • 2015-06-28
  • 1970-01-01
  • 1970-01-01
  • 2017-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-07
  • 2011-02-15
相关资源
最近更新 更多