gpt4 book ai didi

c# - 您是否应该实现 IDisposable.Dispose() 以使其永远不会抛出?

转载 作者:IT王子 更新时间:2023-10-29 03:48:00 26 4
gpt4 key购买 nike

对于 C++ 中的等效机制(析构函数),建议是 it should usually not throw any exceptions .这主要是因为这样做可能会终止您的进程,这很少是一个好策略。

在 .NET 中的等效场景中......

  1. 抛出第一个异常
  2. finally block 作为第一个异常的结果执行
  3. finally block 调用 Dispose() 方法
  4. Dispose() 方法抛出第二个异常

...您的进程不会立即终止。但是,您会丢失信息,因为 .NET 粗暴地将第一个异常替换为第二个异常。因此,调用堆栈上方某处的 catch block 永远不会看到第一个异常。但是,人们通常对第一个异常更感兴趣,因为它通常会提供更好的线索,说明为什么事情开始出错。

由于 .NET 缺乏一种机制来检测代码是否在异常挂起时正在执行,因此似乎只有两种选择如何实现 IDisposable:

  • 始终吞并 Dispose() 中发生的所有异常。不好,因为您最终可能还会吞下 OutOfMemoryException、ExecutionEngineException 等,我通常宁愿在它们发生时拆除进程,而没有另一个异常已经挂起。
  • 让所有异常传播到 Dispose() 之外。不好,因为您可能会丢失有关问题根本原因的信息,请参见上文。

那么,两害相权取其轻?有没有更好的办法?

编辑:澄清一下,我不是在谈论是否主动从 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
{
}
}
}

最佳答案

Framework Design Guidelines(第 2nd 版)将其作为 (§9.4.1):

AVOID throwing an exception from within Dispose(bool) except under critical situations where the containing process has been corrupted (leaks, inconsistent shared state, etc.).

评论[编辑]:

  • 有指导方针,而不是硬性规定。这是一个“避免”而不是“不要”的指南。正如(在评论中)指出的那样,该框架在某些地方打破了这个(和其他)指南。诀窍是知道何时打破准则。在很多方面,这就是熟练工和大师之间的区别。
  • 如果清理的某些部分可能失败,则应提供一个 Close 方法,该方法将抛出异常,以便调用者可以处理它们。
  • 如果您遵循处置模式(如果类型直接包含一些非托管资源,您应该这样做)那么可以从终结器调用 Dispose(bool),从终结器抛出是一个坏主意,会阻止其他对象被最终确定。

我的观点:从 Dispose 中逃逸的异常应该只是那些,如指南中所述,具有足够的灾难性,以至于无法从当前进程中获得进一步的可靠功能。

关于c# - 您是否应该实现 IDisposable.Dispose() 以使其永远不会抛出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/577607/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com