这个问题实际上是这个问题的一个衍生问题,但我认为它值得有自己的答案。
根据ECMA-334第15.13节(关于using
语句,以下称为资源获取):
在资源获取中声明的局部变量是只读的,并且必须包含初始化器。如果嵌套语句尝试通过赋值或
++
和--
运算符修改这些局部变量,或者将它们作为ref
或out
参数传递,则会发生编译时错误。
这似乎解释了为什么下面的代码是非法的。
struct Mutable : IDisposable
{
public int Field;
public void SetField(int value) { Field = value; }
public void Dispose() { }
}
using (var m = new Mutable())
{
// This results in a compiler error.
m.Field = 10;
}
那这个呢?
using (var e = new Mutable())
{
// This is doing exactly the same thing, but it compiles and runs just fine.
e.SetField(10);
}
上面的代码片段在C#中是否未定义和/或非法?如果合法,这段代码与上面摘自规范的节选之间有什么关系?如果它是非法的,那么为什么它能够运行?是否存在一些微妙的漏洞允许它,还是它能够运行只是纯粹的运气(因此,一个人不应该依赖这种看似无害的代码的功能)?
++
或--
运算符吗?还是将其作为ref
或out
参数传递? - Anon.e
这个只读变量的 副本 被修改了。这是明确定义和完全定义的行为。每当一个结构体变量被视为只读时,每次在该变量上调用实例方法时,都会首先进行复制,然后在复制上调用该方法。因此,如果该方法被证明对结构体进行了改变,则只会影响到复制品,而不会保留复制品。来源:在 foreach 循环中更改另一个结构体中的结构体 - Jeppe Stig Nielsen