5

私は C# .NET 4.0 で巨大なプロジェクトに取り組んでいます。System.Net.Socketsから継承されたカスタム クラスがあります。SocketAsyncEventArgsクラス。次のようなもの:

public class SocketTaskArgs : SocketAsyncEventArgs
{
    public SocketTaskArgs()
    {
        Completed += someEventhHandler;
    }

    public void CleanUp()
    {
        Completed -= someEventhHandler;
    }

    /* 
        There is a lot of code here that is unimportant at the moment.
    */
}

そこで、CleanUp() メソッドの内容を Dispose(bool) メソッドに移動したいと思いました。

最初に、基本クラス SocketAsyncEventArgs のソース コードを確認しました (ソースとしてメタデータが表示されるように [定義へ移動] を使用)。このクラスは IDisposable インターフェイスを実装していることがわかりました。Dispose(bool) メソッドをオーバーライドする必要があるだけですね。(詳細については、MSDN の IDisposable インターフェイス、「IDisposable と継承階層」セクションを参照してください)。私にとって新しいことは何もありません... 残念ながら、SocketAsyncEventArgs クラスは次のように実装されています。

public class SocketAsyncEventArgs : EventArgs, IDisposable
{
    public void Dispose();

    //some other stuff here
}

つまり、保護されているのではなくプライベートとして実装されているため、Dispose(bool)メソッドをオーバーライドする方法はありません...この理由は何ですか?

次に、 MSDN のSocketAsyncEventArgs.Dispose()メソッドについて読みました。面白いことに、次のセクションが含まれています。

継承者への注意事項

Disposeは、他のオブジェクトから複数回呼び出すことができます。Dispose(Boolean)をオーバーライドするときは、 Disposeの以前の呼び出しで以前に破棄されたオブジェクトを参照しないように注意してください 。Dispose(Boolean)の実装方法の詳細については、Dispose メソッドの実装を参照してください。

待って…何?

Dispose(Boolean)をオーバーライドすると、...

Dispose(Boolean) をオーバーライドするにはどうすればよいですか?

この場合、IDisposable インターフェイスを実装するための推奨される方法は何ですか?

4

1 に答える 1

4

IDisposable子クラスへの実装を妨げるものはないようです。次の例を見てください。

public class DisposableParent : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("The parent was disposed.");
    }
}

public class DisposableChild : DisposableParent, IDisposable
{
    public new void Dispose()
    {
        base.Dispose();
        Console.WriteLine("The child was disposed.");
    }
}

public class Program
{
    public static void Main()
    {
         using (DisposableChild c = new DisposableChild()) { }
         Console.ReadKey(true);
    }
}

次の出力が得られます。

親は処分しました。

その子は処分されました。

コンパイラは、子クラスの親クラスの破棄を隠すことについて警告するため、new演算子を使用するとその警告が取り除かれますDispose。子クラスから基本クラスを呼び出すことを確認してください (そして、正しい方法で実装してください)。

子の破棄は次のようになります。

public class DisposableChild : DisposableParent, IDisposable
{
    private bool _disposed = false;

    public new void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (!_disposed)
            {
                base.Dispose();
                Console.WriteLine("The child was disposed.");
                _disposed = true;
            }
        }
    }
}

そして、はい、これは次のようなことをしても機能します:

using (DisposableParent p = new DisposableChild())
{

}

しかし、このようなものはそれを壊す可能性があります:

public class Program
{
    public static void Main()
    {
        DisposableChild c = new DisposableChild();
        DisposeOfIt(c);

        Console.ReadKey(true);
    }

    public static void DisposeOfIt(DisposableParent p)
    {
        p.Dispose();
    }
}

親が破棄されたことのみを出力します。したがって、このメソッドを使用した場合、オブジェクトの有効期間を制御することに注意する必要があります。

于 2015-07-20T19:21:34.127 に答える