当前位置: 首页 > 编程语言 > C#

为什么readonly结构上的mutation没有被破坏?分享

时间:2023-04-10 20:20:40 C#

C#:为什么readonly结构上的mutation没有被破坏?在C#中,如果您有这样的结构:structCounter{privateint_count;publicintValue{get{return_count;}}publicintIncrement(){返回++_count;你有这样一个程序:staticreadonlyCountercounter=newCounter();staticvoidMain(){//打印增量函数的新值Console.WriteLine(counter.Increment());//打印存储在项目中的值Console.WriteLine(counter.Value);}这个程序的输出是:10这似乎是完全错误的。我希望输出是两个1(如果Counter是一个类,或者如果structCounter:ICounter和counter是ICounter)或者它是一个编译错误。我意识到在编译时检测到这一点是一件相当困难的事情,但这种行为似乎违背了逻辑。这种行为是否有超出实施难度的原因?结构是值类型,因此具有值类型语义。这意味着每次访问结构时,基本上都是在处理结构值的副本。在您的示例中,您不更改原始结构,只更改它的临时副本。详细解释见此处:为什么可变结构是邪恶的在.NET中,结构实例方法在语义上等同于具有结构类型的额外ref参数的静态结构方法。因此,给定声明:structBlah{publicintvalue;publicvoidAdd(intAmount){value+=Amount;}publicstaticvoidAdd(refBlahit;intAmount;it.value+=Amount;}}方法调用:someBlah.Add(5);Blah.Add(refsomeBlah,5);在语义上是等价的,除了一个区别:只有当someBlah是允许的可变存储位置(变量、字段等)时才调用后一个调用,如果它是只读存储位置或临时值(导致读取属性等)则不会调用。.net语言的设计者面临一个问题:不允许在只读结构上使用任何成员函数会非常烦人,但他们不想让成员函数写入只读变量。他们决定“踢"它,并使其在只读结构上调用实例方法将复制该结构,调用该函数,然后丢弃它。这将右下角编写调用底层结构的实例方法的速度并使其尝试使用更新只读结构上的底层结构的方法将具有不同的破坏语义。如果直接传递结构,则可以实现这一点。请注意,在没有副本的情况下,副本花费的额外时间很难产生正确的语义。我在.net中的主要问题之一是仍然没有(至少4.0,可能是4.5)结构成员函数可以用来指示它是否修改Gotthis的属性。人们谈论的是结构是不可变的,而不是提供允许结构安全地提供变异方法的工具。尽管所谓的“不可变”结构是一个谎言。可变存储位置中的所有非平凡值类型都是可变的,所有装箱值类型也是如此。使结构“不可变”可能会迫使人们在只想更改一个字段时重写整个结构,但是由于struct1=struct2struct2通过复制所有公共和私有字段来改变struct1,并且结构的类型定义无能为力为了防止(除了没有任何字段)它没有任何东西可以防止结构成员的意外突变。此外,由于线程问题,结构在其字段之间强制执行任何类型的不可变关系的能力非常有限。恕我直言,对于允许任意字段访问的结构通常更好,明确表示任何接收结构的代码都必须检查其字段是否满足所有必需条件,而不是试图阻止不符合条件的结构的形成。以上是C#学习教程:C#:为什么readonly结构上的mutation没有被销毁?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: