¿Debería implementar IDisposable.Dispose () para que nunca arroje?

Para el mecanismo equivalente en C ++ (el destructor), el consejo es que generalmente no debería lanzar ninguna excepción. Esto se debe principalmente a que al hacerlo puede terminar su proceso, lo que rara vez es una buena estrategia.

En el escenario equivalente en .NET ...

Se lanza una primera excepción Un bloque finalmente se ejecuta como resultado de la primera excepciónl bloque finalmente llama a un método Dispose () El método Dispose () arroja una segunda excepción

... su proceso no finaliza de inmediato. Sin embargo, pierde información debido a que .NET reemplaza sin excepción la primera excepción con la segunda. Por lo tanto, un bloque catch en algún lugar de la pila de llamadas nunca verá la primera excepción. Sin embargo, uno suele estar más interesado en la primera excepción porque normalmente da mejores pistas de por qué las cosas comenzaron a salir mal.

Dado que .NET carece de un mecanismo para detectar si el código se está ejecutando mientras hay una excepción pendiente, parece que en realidad solo hay dos opciones para implementar IDisposable:

Siempre trague todas las excepciones que ocurren dentro de Dispose (). No es bueno, ya que también podría terminar tragándose OutOfMemoryException, ExecutionEngineException, etc., que generalmente preferiría dejar el proceso cuando ocurran sin otra excepción ya pendiente.Deje que todas las excepciones se propaguen desde Dispose (). No es bueno, ya que podría perder información sobre la causa raíz de un problema, consulte más arriba.

Entonces, ¿cuál es el menor de los dos males? ¿Hay una mejor manera?

EDITA: Para aclarar, no estoy hablando de lanzar activamente excepciones de Dispose () o no, estoy hablando de dejar que las excepciones lanzadas por los métodos llamados por Dispose () se propaguen de Dispose () o no, por ejemplo:

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
        {
        }
    }
}

Respuestas a la pregunta(8)

Su respuesta a la pregunta