简体   繁体   English

在using语句中修改值类型变量

[英]modify a value-type variable in a using statement

In C#, if I have the following struct: 在C#中,如果我具有以下结构:

internal struct myStruct : IDisposable
{
    public int x;

    public void Dispose()
    {
        x = 0;
    }
}

then do this in Main: 然后在Main中执行以下操作:

using (myStruct myStruct = new myStruct())
{
   myStruct.x = 5;
}

it fails saying that myStruct is readonly. 它不能说myStruct是只读的。 That makes sense as myStruct is a value-type. 这很有意义,因为myStruct是一种值类型。

Now if I add the folling function to the struct: 现在,如果将以下功能添加到struct中:

public void myfunc(int x)
{
    this.x = x;
}

and change the Main code to this: 并将主代码更改为此:

using (myStruct myStruct = new myStruct())
{
    myStruct.myfunc(5);
    Console.WriteLine(myStruct.x);
}

it works. 有用。 Why ? 为什么呢

The short answer is "because the C# specification says so". 简短的答案是“因为C#规范是这样说的”。 Which, I admit, may be a bit unsatisfying. 我承认,这可能有些令人不满意。 But that's how it is. 但是,就是这样。

The motivation is, I'm sure, as commenter Blogbeard suggests: while it's practical to enforce read-only on the field access, it's not practical to do so from within a type. 可以肯定的是,正如评论者Blogbeard所言,这样做的动机是:虽然对字段访问强制实施只读是可行的,但在类型内执行只读操作却并不可行。 After all, the type itself has no way to know how a variable containing a value of that type was declared. 毕竟,类型本身无法知道如何声明包含该类型值的变量。

The key part of the C# specification (from the v5.0 spec) is here, on page 258 (in the section on the using statement): C#规范(来自v5.0规范)的关键部分在此处,在第258页(在using语句的部分中):

Local variables declared in a resource-acquisition are read-only, and must include an initializer. 在资源获取中声明的局部变量是只读的,并且必须包含初始化程序。 A compile-time error occurs if the embedded statement attempts to modify these local variables (via assignment or the ++ and operators), take the address of them, or pass them as ref or out parameters. 如果嵌入式语句尝试修改这些局部变量(通过赋值或++和运算符),获取其地址或将其作为ref或out参数传递,则会发生编译时错误。

Since in the case of a value type, the variable itself contains the value of the object rather than a reference to an object, modifying any field of the object via that variable is the same as modifying the variable, and is so a "modification via assignment", which is specifically prohibited by the specification. 由于在值类型的情况下,变量本身包含对象的值,而不是对对象的引用,因此,通过该变量修改对象的任何字段与修改变量相同,因此,“通过分配”,这是规范明确禁止的。

This is exactly the same as if you had declared the value type variable as a field in another object, with the readonly modifier. 这与使用readonly修饰符将值类型变量声明为另一个对象中的字段的情况完全相同。

But note that this is a compile-time rule, enforced by the C# compiler, and that there's no way for the compiler to similarly enforce the rule for a value type that modifies itself. 但是请注意,这是由C#编译器强制执行的编译时规则,并且编译器无法类似地对自己修改的值类型强制执行该规则。


I will point out that this is one of many excellent reasons that one should never ever implement a mutable value type. 我将指出,这是许多绝不应该实现可变值类型的绝妙原因之一。 Mutable value types frequently wind up being able to be modified when you don't want them to be, while at the same time find themselves failing to be modified when you do want them to be (in completely different scenarios from this one). 可变值类型经常在您不希望被修改时就可以被修改,而与此同时,您发现自己却不想被修改(在与此完全不同的场景中)。

If you treat a value type as something that is truly a value, ie a single value that is itself never changing, they work much better and find themselves in the middle of many fewer bugs. 如果您将值类型视为真正的值,即,一个永不改变的值,则它们会更好地工作,并且发现自己处于更少的错误中间。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM