我发现人们声称在一个类中使用所有只读字段并不一定会使该类的实例不可变,因为即使在初始化(构造)之后也有更改只读字段值的“方法”。
如何?有什么方法?
所以我的问题是什么时候我们才能在 C# 中真正拥有一个“真正的”不可变对象(immutable对象),我可以在线程中安全地使用它?
匿名类型也会创建不可变对象(immutable对象)吗?有人说 LINQ 在内部使用不可变对象(immutable对象)。究竟如何?
最佳答案
您在其中问了大约五个问题。我会回答第一个:
Having all readonly fields in a class does not necessarily make that class's instance immutable because there are "ways" to change the readonly field values even after construction. How?
是否可以在构造后更改只读字段?
是的,如果您足够信任以打破只读规则。
它是如何工作的?
进程中的每一位用户内存都是可变的。像只读字段这样的约定可能会使某些位看起来是不可变的,但如果你足够努力,你可以改变它们。例如,您可以采用不可变对象(immutable对象)实例,获取其地址,然后直接更改原始位。这样做可能需要大量的智慧和内存管理器内部实现细节的知识,但内存管理器会以某种方式设法改变该内存,因此如果您足够努力,您也可以做到。如果您足够信任,您还可以使用“私有(private)反射”来破坏安全系统的各个部分。
根据定义,完全可信的代码可以打破安全系统的规则。这就是“完全信任”的意思。如果您的完全可信代码选择使用私有(private)反射或不安全代码等工具来破坏内存安全规则,则允许完全可信代码这样做。
请不要。这样做是危险和困惑的。内存安全系统旨在让您更容易推断代码的正确性;故意违反其规则是个坏主意。
那么,“只读”是一个谎言吗?好吧,假设我告诉过你,如果每个人都遵守规则,那么每个人都会得到一 block 蛋糕。蛋糕是骗人的吗?该声明不是“您将分得一杯羹”的声明。这就是如果每个人都遵守规则,您将分得一杯羹的说法。如果有人作弊并拿走了你的一片,你就没有蛋糕了。
类的只读字段是只读的吗?可以,但前提是每个人都遵守规则。所以,只读字段不是“谎言”。契约(Contract)是,如果每个人都遵守系统规则,那么该字段将被视为只读。如果有人违反了规则,那么也许不是。这并不能使“如果每个人都遵守规则,该字段是只读的”这句话成为谎言!
一个你没有问但也许应该问的问题是结构字段上的“只读”是否也是一个“谎言”。参见 Does using public readonly fields for immutable structs work?关于这个问题的一些想法。结构上的只读字段比类上的只读字段更像是一个谎言。
至于您的其余问题 -- 我认为如果您每个问题问一个问题,而不是每个问题五个问题,您会得到更好的结果。
关于C# 和不可变性和只读字段……谎言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6722571/