来自C#4.0第7.5.5节。
如果M是在值类型中声明的实例函数成员:
- [...]
- 如果E未被归类为变量,则创建E类型的临时局部变量,并将E的值分配给 变量。然后将E重新分类为对该临时的引用 局部变量。临时变量可以在其中访问 M,但不是以任何其他方式。因此,只有当E是真实变量时 (什么是真正的变量......?)调用者可以观察到的变化 M对此做出了贡献。
Eric Lippert接着说:
这一点说明了另一种组合方式 可变性和按值复制的语义可能会导致麻烦。对于 例如,readonly字段在之后不被分类为变量 构造函数运行。因此,尝试调用一个变异的方法 值类型的只读字段的内容成功但实际上是成功的 变异副本!通过避免可变值类型来避免这些问题 共
如何重现Eric描述的场景呢?我尝试了以下内容。它像我期望的那样出错:
struct A
{
public readonly int mutableReadonlyField;
public A(int originalValue)
{
mutableReadonlyField = originalValue;
}
public A MethodThatMutatesTheContentsOfAReadOnlyField(int mutate)
{
this.mutableReadonlyField = mutate;//Constructor has run so mutableReadonlyField is a temporary local variable
//ERROR: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
A newA = this;//Is this a true variable?
return newA;
}
}
答案 0 :(得分:5)
我在我的博客上举了一个例子:
http://ericlippert.com/2008/05/14/mutating-readonly-structs/
问题在于我的句子片段“值类型的只读字段”含糊不清且具有误导性。我打算将它表示 class 中的只读字段,其中字段是值类型S ,但显然更自然的读取是将其作为只读字段在S本身。我应该完全改写这句话。为错误道歉。
回答你的另一个问题:形容词“true”是不必要的。如果它只是说“因此,只有当E是变量时,调用者才有可能观察到M对此做出的改变。”