C#处理对象

thd*_*thd 2 c# dispose idisposable

我知道当你有以下代码时,在StreamReader对象上调用Dispose()方法:

//Sample 1
using (StreamReader sr1 = new StreamReader(@"C:\Data.txt"))
{
    string s1 = sr1.ReadToEnd();
    //Do something with s1...
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您编写这样的代码(示例2),Dispose()方法也会被调用吗?

//Sample 2
StreamReader sr2 = new StreamReader(@"C:\Data.txt");
using (sr2)
{
    string s2 = sr2.ReadToEnd();
    //Do something with s2...
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 9

是的,一点没错.详情见第8.13节.您的确切问题没有简明陈述,但是:

表格的使用声明

using (expression) statement
Run Code Online (Sandbox Code Playgroud)

具有相同的三种可能的扩展,但在这种情况下ResourceType隐式地是表达式的编译时类型,并且资源变量在嵌入语句中是不可访问的,并且是不可访问的.

所提到的"三种可能的扩展"涵盖了同时声明变量的更常见情况.基本上重要的是除了变量的范围外,它的行为方式相同.Dispose仍然会被调用 - 否则根本就没有必要using发表声明:)

请注意,两者在块中的有效性方面并不完全相同,因为using语句声明的变量是只读的.所以这是有效的:

// Warning but no error
MemoryStream ms = new MemoryStream();
using (ms)
{
    ms = null;
}
Run Code Online (Sandbox Code Playgroud)

但这不是:

using (MemoryStream ms = new MemoryStream())
{
    // error CS1656: Cannot assign to 'ms' because it is a 'using variable'
    ms = null;
}
Run Code Online (Sandbox Code Playgroud)

请注意,即使在有效的情况下,它的原始ms也用于处置.编译器明确了这一点:

警告CS0728:可能不正确地分配给本地'ms',这是using语句或lock语句的参数.Dispose调用或解锁将发生在本地的原始值上.

请注意,表单不会生成警告:

// No warning
MemoryStream ms;
using (ms = new MemoryStream())
{
    ms = null;
}
Run Code Online (Sandbox Code Playgroud)

另一方面,除此之外,他们真的会以同样的方式行事.

编辑:正如bzlm所指出的那样,在using声明之后变量仍然在范围内的事实意味着它通常不是一个好主意.但是,已经放置的物体并不总是不可用.例如:

MemoryStream ms = new MemoryStream();
using (ms) 
{
    // Do stuff
}
byte[] data = ms.ToArray();
Run Code Online (Sandbox Code Playgroud)

这样可以正常工作 - MemoryStream即使数据处理完毕也可以保存数据.虽然我觉得有点不对劲.


Gre*_*reg 9

是的,Dispose()在两个例子中都会被调用.它们在功能上是等效的,除了在第二个例子中,处理的StreamReader仍然在范围内.因此,第一种方法是优选的,因为使用被处置物体通常是坏主意.

然而,正如其他人所指出的那样,使用被处理物体有时是可以的.在这种情况下,您可能想要使用第二个示例.但是你必须知道你在做什么,如果可能的话我会尽量避免.

  • 第一种形式是首选的,以避免用sr2污染封闭函数的范围,在使用构造指向已处置的对象之后. (2认同)