对于C++(析构函数)中的等效机制,建议通常不应抛出任何异常.这主要是因为这样做可能会终止您的流程,这很少是一个好策略.
在.NET的等效场景中......
...您的流程不会立即终止.但是,由于.NET无法用第二个异常替换第一个异常,因此会丢失信息.因此,调用堆栈上某处的catch块将永远不会出现第一个异常.然而,人们通常对第一个例外更感兴趣,因为这通常会提供更好的线索,说明为什么事情开始出错.
由于.NET缺少一种机制来检测代码是否在异常处于挂起状态时被执行,因此似乎只有两种选择可以实现IDisposable:
那么,两个邪恶中哪一个较小?有没有更好的办法?
编辑:为了澄清,我不是在谈论积极抛出Dispose()或不抛出异常,我说的是让Dispose()调用的方法抛出的异常传播出Dispose()或不传播,例如:
using System;
using System.Net.Sockets;
public sealed class NntpClient : IDisposable
{
private TcpClient tcpClient;
public NntpClient(string hostname, int port)
{
this.tcpClient = new TcpClient(hostname, port);
}
public void Dispose()
{
// Should we implement like this or leave away the try-catch?
try
{
this.tcpClient.Close(); // Let's assume that this might throw
}
catch
{
}
}
}
Run Code Online (Sandbox Code Playgroud) 我注意到using我的代码中嵌套语句的级别最近有所增加.究其原因,可能是因为我使用越来越多的async/await格局,这往往增加了至少一个以上using的CancellationTokenSource或CancellationTokenRegistration.
那么,如何减少嵌套using,所以代码看起来不像圣诞树?之前已经提出了类似的问题,我想总结一下我从答案中学到的东西.
using而不缩进.一个假的例子:using (var a = new FileStream())
using (var b = new MemoryStream())
using (var c = new CancellationTokenSource())
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
这可能有用,但通常会有一些代码using(例如,创建另一个对象可能为时过早):
// ...
using (var a = new FileStream())
{
// ...
using (var b = new MemoryStream())
{
// ...
using (var c = new CancellationTokenSource())
{
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
IDisposable)的对象组合成单个对象using,例如:// …Run Code Online (Sandbox Code Playgroud) 我正在审查我的同事的一些WPF代码,这是一个基于组件的库,UserControl包含许多async void事件和命令处理程序.这些方法目前不在内部实现任何错误处理.
代码简而言之:
<Window.CommandBindings>
<CommandBinding
Command="ApplicationCommands.New"
Executed="NewCommand_Executed"/>
</Window.CommandBindings>
Run Code Online (Sandbox Code Playgroud)
private async void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
// do some fake async work (and may throw if timeout < -1)
var timeout = new Random(Environment.TickCount).Next(-100, 100);
await Task.Delay(timeout);
}
Run Code Online (Sandbox Code Playgroud)
抛出异常但未在内部观察到的异常NewCommand_Executed 只能在全局级别上处理(例如,使用AppDomain.CurrentDomain.UnhandledException).显然,这不是一个好主意.
我可以在本地处理异常:
private async void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
try
{
// do some fake async work (throws if timeout < -1)
var timeout = new …Run Code Online (Sandbox Code Playgroud)