Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.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# 如果在使用语句结束之前返回,会发生什么?会叫警察吗?_C#_.net_Dispose_Idisposable_Using Statement - Fatal编程技术网

C# 如果在使用语句结束之前返回,会发生什么?会叫警察吗?

C# 如果在使用语句结束之前返回,会发生什么?会叫警察吗?,c#,.net,dispose,idisposable,using-statement,C#,.net,Dispose,Idisposable,Using Statement,我有以下代码 using(MemoryStream ms = new MemoryStream()) { //code return 0; } dispose()方法在的末尾使用语句括号}调用,对吗?由于I在using语句结束之前返回,因此内存流对象是否会被正确处理?这里发生了什么?是,将调用Dispose。只要执行离开using块的作用域,它就会被调用,不管它以什么方式离开块,无论是块的执行结束、return语句还是异常 正如@Noldorin正确指出的,在代码中使用和块

我有以下代码

using(MemoryStream ms = new MemoryStream())
{
     //code
     return 0;
}

dispose()
方法在
的末尾使用
语句括号
}
调用,对吗?由于I
using
语句结束之前返回
,因此
内存流
对象是否会被正确处理?这里发生了什么?

是,将调用
Dispose
。只要执行离开
using
块的作用域,它就会被调用,不管它以什么方式离开块,无论是块的执行结束、
return
语句还是异常

正如@Noldorin正确指出的,在代码中使用
块会被编译成
try
/
finally
,并在
finally
块中调用
Dispose
。例如,以下代码:

using(MemoryStream ms = new MemoryStream())
{
     //code
     return 0;
}
实际上成为:

MemoryStream ms = new MemoryStream();
try
{
    // code
    return 0;
}
finally
{
    ms.Dispose();
}
因此,由于
finally
保证在
try
块完成执行后执行,无论其执行路径如何,
Dispose
保证被调用,无论发生什么情况

有关详细信息,请参阅

附录:

需要补充一点:因为
Dispose
保证会被调用,所以在实现
IDisposable
时,确保
Dispose
从不引发异常几乎总是一个好主意。不幸的是,在调用
Dispose
时,核心库中有一些类确实会在某些情况下抛出--我在看你,WCF服务引用/客户端代理当这种情况发生时,如果在异常堆栈展开期间调用了
Dispose
,则很难跟踪原始异常,因为原始异常会被吞没,而由
Dispose
调用生成的新异常会被吞没。这可能令人沮丧得发狂。还是说这令人沮丧?两个中的一个。也许两者都有

您的MemoryStream对象将被正确处理,无需担心

使用
using
语句,不管完成路径如何,对象都将被丢弃

进一步阅读


编译后,请查看reflector中的代码。您会发现编译器重构代码以确保在流上调用dispose。

使用
语句的行为与
try。。。最后
块,因此将始终在任何代码退出路径上执行。但是,我相信它们会受到很少且罕见的情况的影响,在这种情况下,
最终
块不会被调用。我记得的一个例子是,如果前台线程退出,而后台线程处于活动状态:除GC之外的所有线程都暂停,这意味着
最终
块不会运行

显而易见的编辑:除了让它们处理IDisposable对象的逻辑之外,它们的行为是相同的

奖励内容:可以堆叠(类型不同的地方):

以及逗号分隔(其中类型相同):


我想您会发现,它通过调用finally中的
Dispose
,有效地编译成了try-finally块,因此它有效地完成了
finally
的实现,正如您所描述的那样。@Noldorin:没错。虽然我想我可以说得很清楚。另请注意,在某些情况下,finally块不能保证执行,例如使用Environment.FailFast和发生StackOverFlowException。@C.McAtackney:这也是一个很好的观点。还有,IIRC,OutOfMemoryException;基本上,如果您无法捕获异常,因为它是一个关键的执行失败,则不会调用Dispose。当然,在这种情况下,程序和分配给它的任何内存都会崩溃,因此在99.9%的情况下,这不是问题,除非你正在做一些不可靠的事情,比如用dispose方法写入文件。除了灾难性的程序崩溃之外,也就是说,您不应该在WCF中使用“using()”语句-有关详细信息,请参阅。下面是我用于WCF代理的一个片段:“WCFProxy variableName=null;尝试{variableName=new WCFProxy();//此处的TODO代码variableName.Proxy.Close();variableName.Dispose();}捕获(异常){if(variableName!=null&&variableName.Proxy!=null){variableName.Proxy.Abort();}throw;}Aaap。。。我收回这句话。经过一些非常认真的搜索之后,我发现了一个近乎重复的问题:现在,这个问题的提问方式完全不同,但最终的问题几乎是一样的。我想我们毕竟可以认为这是一个DUPE。根据StAcExver中的另一个答案,对于第二个例子(逗号分隔),不应该指定第二个参数的类型。我没有回到以前的语言版本,所以我不知道是一直都是这样,还是Roslyn的一个小变化。
using (SqlConnection conn = new SqlConnection("string"))
using (SqlCommand comm = new SqlCommand("", conn))
{

}
using (SqlCommand comm = new SqlCommand("", conn), 
       comm2 = new SqlCommand("", conn))
{

}