C# 为什么要使用块和异常?
我最近在使用语句时遇到了异常处理问题。问题在于,在“using block”中抛出的异常可能会被吞没,例如查看代码:C# 为什么要使用块和异常?,c#,.net,using-statement,C#,.net,Using Statement,我最近在使用语句时遇到了异常处理问题。问题在于,在“using block”中抛出的异常可能会被吞没,例如查看代码: class DisposableObject : IDisposable { public void Dispose() { throw new Exception("dispose"); } } class Program { static void Main() { try {
class DisposableObject : IDisposable
{
public void Dispose()
{
throw new Exception("dispose");
}
}
class Program
{
static void Main()
{
try
{
using (var obj = new DisposableObject())
{
throw new Exception("using");
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
在本例中,您将在输出中看到“dispose”,第一个异常将被忽略,您永远不会知道它。经过搜索,我找到了一篇关于使用block的常见错误的文章。但我的问题不是如何避免异常吞咽,我想知道MS为什么决定使用块来打开包
try
{
...
}
finally
{
}
而不是其他,例如,他们可以使用以下方式展开:
//this code prevents exception swallowing
try
{
...
}
catch (Exception ex)
{
try
{
if (obj != null)
obj.Dispose();
}
catch (Exception disposeEx)
{
throw new AggregateException(ex, disposeEx);
}
throw;
}
if(obj != null)
obj.Dispose();
因为创建
using()
块时,aggregateeexception
不存在
还因为Dispose()
实际上不应该抛出
最后,因为您的示例和
Finally
块在异常过滤器、堆栈展开和关键区域方面存在细微的语义差异。它们可能创建了AggregateException。我不认为AggregateException的缺失是个问题,它是一个非常简单的类。另外,如果Dispose确实不应该抛出异常,但事实上Dispose可以在许多流行的库中抛出异常,例如WCF(客户端代理可以在disposing时抛出异常)。第三,我刚刚编写了示例代码,演示了如何避免吞咽,它可以用finally block编写(我想我可能错了)。这是一个聪明的问题。他们本可以这样做以防止错误丢失。Wait也有类似的问题。除了一个错误(通常不确定是哪一个错误)之外,它会丢弃所有错误。@usr使用代码中未出现的不同类型创建新异常似乎有问题。早些时候,C#有一个“毫不意外”的设计,尽管现在肯定已经放松了。@mikez Alternative,他们可以在第二个异常上将第一个异常放入某些属性中。