Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么结构的字段在using语句之后被重置?_C#_Struct_Idisposable - Fatal编程技术网

C# 为什么结构的字段在using语句之后被重置?

C# 为什么结构的字段在using语句之后被重置?,c#,struct,idisposable,C#,Struct,Idisposable,我注意到IDisposable结构有一些奇怪的行为。 dispose方法似乎是在字段设置为默认值的新实例上调用的 公共静态类示例 { 公共静态真空总管 { var数据=新的MyStruct; 使用数据 { data.Foo=某个字符串; Console.WriteLinedata.Foo;//一些字符串 } Console.WriteLinedata.Foo;//一些字符串 } } 公共结构MyStruct:IDisposable { 公共字符串Foo; 公共空间处置 { Console.wri

我注意到IDisposable结构有一些奇怪的行为。 dispose方法似乎是在字段设置为默认值的新实例上调用的

公共静态类示例 { 公共静态真空总管 { var数据=新的MyStruct; 使用数据 { data.Foo=某个字符串; Console.WriteLinedata.Foo;//一些字符串 } Console.WriteLinedata.Foo;//一些字符串 } } 公共结构MyStruct:IDisposable { 公共字符串Foo; 公共空间处置 { Console.writelinefo;//null! Foo=一些字符串; } } 我假设发生这种情况是因为对象在finally块中被强制转换为IDisposable,并且因为这里有一个值类型,所以创建了一个新实例。 我不明白的是为什么字段没有复制到新实例? 在框选结构时,将复制字段:

var s=新的MyStruct; s、 Foo=1; var s2=MyStructobjects; Console.WriteLines.Foo//1. Console.WriteLines2.Foo//1.
对于值类型,变量数据将在using语句的开头复制到另一个未命名的临时文件中。根据规范,这个副本的行为就像被装箱到IDisposable和Dispose调用note一样,但是C编译器实际上并没有装箱这个值,在文章的末尾会有更多的介绍。这记录在以下文件中:

表单的using语句

using (ResourceType resource = expression) statement
using (expression) statement
对应于三种可能的扩展之一。如果ResourceType是不可为null的值类型,则扩展为

{
    ResourceType resource = expression;
    try {
        statement;
    }
    finally {
        ((IDisposable)resource).Dispose();
    }
}
注意,using语句不是一个声明,只是一个表达式。本规范还包括以下内容:

表单的using语句

using (ResourceType resource = expression) statement
using (expression) statement
具有相同的三种可能的扩展。在本例中,ResourceType隐式表示表达式的编译时类型(如果有)。否则,接口IDisposable本身将用作ResourceType。资源变量在嵌入语句中不可访问,并且对嵌入语句不可见

因此,您对数据的修改不会在Dispose中看到,因为已经创建了副本。VS2019附带的C编译器的相对较新版本将针对这种情况发出警告

值是否已装箱

不。尽管在规范中出现了cast,甚至对C进行了一些反编译,但编译器是允许的,而且事实上不会对值进行装箱。Eric Lippert在评论中的链接也包含了一些关于这方面的补充细节。为了了解实际情况,让我们看看最后一部分中的IL:

IL_0023: ldloca.s 1
IL_0025: constrained. MyStruct
IL_002b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0030: endfinally
首先,将未命名的临时文件加载回计算堆栈。这是前面提到的未修改副本。下一步,魔法将通过网络发生。这是一条特殊指令,通知JIT正在直接对该类型进行调用,如果该类型是实现该方法的值类型,则不需要通过接口进行虚拟调用

Eric的文章提到了对C规范的更新,澄清了对装箱的省略,这可能就是这一点:

允许实现以不同方式实现给定的using语句,例如出于性能原因,只要行为与上述扩展一致


对于值类型,变量数据将在using语句的开头复制到另一个未命名的临时文件中。根据规范,这个副本的行为就像被装箱到IDisposable和Dispose调用note一样,但是C编译器实际上并没有装箱这个值,在文章的末尾会有更多的介绍。这记录在以下文件中:

表单的using语句

using (ResourceType resource = expression) statement
using (expression) statement
对应于三种可能的扩展之一。如果ResourceType是不可为null的值类型,则扩展为

{
    ResourceType resource = expression;
    try {
        statement;
    }
    finally {
        ((IDisposable)resource).Dispose();
    }
}
注意,using语句不是一个声明,只是一个表达式。本规范还包括以下内容:

表单的using语句

using (ResourceType resource = expression) statement
using (expression) statement
具有相同的三种可能的扩展。在本例中,ResourceType隐式表示表达式的编译时类型(如果有)。否则,接口IDisposable本身将用作ResourceType。资源变量在嵌入语句中不可访问,并且对嵌入语句不可见

因此,您对数据的修改不会在Dispose中看到,因为已经创建了副本。VS2019附带的C编译器的相对较新版本将针对这种情况发出警告

值是否已装箱

不。尽管在规范中出现了cast,甚至对C进行了一些反编译,但编译器是允许的,而且事实上不会对值进行装箱。Eric Lippert在评论中的链接也包含了一些关于这方面的补充细节。为了了解实际情况,让我们看看最后一部分中的IL:

IL_0023: ldloca.s 1
IL_0025: constrained. MyStruct
IL_002b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0030: endfinally
首先,将未命名的临时文件加载回计算堆栈。这是前面提到的未修改副本。下一步,魔法将通过网络发生。T his是一条特殊指令,通知JIT正在直接对该类型进行调用,如果该类型是实现该方法的值类型,则不需要通过接口进行虚拟调用

Eric的文章提到了对C规范的更新,澄清了对装箱的省略,这可能就是这一点:

允许实现以不同方式实现给定的using语句,例如出于性能原因,只要行为与上述扩展一致


因为使用创建数据的副本。您使用的是什么版本的VS/C?2019年,我收到一条CS0728警告,其中明确指出了问题……请参阅,并给出了合理的结论,即您应该使用任何合理的现代版本的语言。如果您没有使用该语言的现代版本,则可能值得添加一个特定于语言的标记。任何时候,如果您有一个未声明为只读结构的结构,您可能处于危险的境地。readonly struct可以使您避免出现这样的错误,因为使用它可以创建数据的副本。您使用的是什么版本的VS/C?2019年,我收到一条CS0728警告,其中明确指出了问题……请参阅,并给出了合理的结论,即您应该使用任何合理的现代版本的语言。如果您没有使用该语言的现代版本,则可能值得添加一个特定于语言的标记。任何时候,如果您有一个未声明为只读结构的结构,您可能处于危险的境地。readonly struct可以使您避免出现这样的错误。