2

使い捨てクラスについていくつか質問があります。いくつかの使い捨てメンバーを持つIDisposable実装クラスがあるとします。メソッドを実装しましたDispose() 。つまり、次のとおりです。

class BaseCustom: IDisposable
{
    private System.Net.Sockets.TcpClient tc;
    private System.Net.Sockets.NetworkStream ns;
    public string str;
    public int i;

    public BaseCustom(string host, int port)
    {
        tc = new System.Net.Sockets.TcpClient(host, port);
        ns = tc.GetStream();
    }

    // some other methods work on members (i, str, tc, ns)

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (ns != null)
            {
                ns.Close();
                ns = null;
            }
            if (tc != null)
            {
                tc.Close();
                tc = null;
            }
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

Q1)アンマネージリソースがないので、ファイナライザを抑止してもいいですか? (ここのコードのメモを読んでください)

Q2)使い捨てメンバを破棄して GC を抑制したので、ここのintandstringメンバはどうなりますか? それらも処理する必要がありますか?

Q3)tc現在の解放はns適切ですか?Close()呼び出しと呼び出しについて、バージョン間で.NET参照内に違いがあります。Dispose()

派生クラスがあるとします。

class DerivedCustom : BaseCustom
{
    public string cstr;
    public int ci;

    public DerivedCustom(string host, int port)
        : base(host, port)
    {}

    // some extra methods
}

Q4) Q2 に関連している可能性があります。ここで sをオーバーライドする必要がありますDispose()か? 派生クラスにアンマネージまたは使い捨てのリソースを導入しません。それをそのままにしておいても安全ですか (つまり、ベースの破棄メカニズムを信頼します)? GC が抑制された場合 (派生でも抑制されます) はどうなりますciか? cstrまた、Q1 に関連して、ファイナライザーは必要ですか?

Q5)ベースが抽象クラスだったら?

Q6)これは興味深いです。このコードは、FxCop 1.36 での使い捨てに関する警告を表示しません。ただし、使い捨てメンバーをに追加してDerivedCustom 、使い捨てメソッドをオーバーライドしない場合 (したがって、新しいメンバーを処理しない場合):

class DerivedCustom : BaseCustom
{
    public string cstr;
    public int ci;
    // below is the only extra line
    public System.Net.Sockets.TcpClient ctc = new System.Net.Sockets.TcpClient("ho.st", 1234);

    public DerivedCustom(string host, int port)
        : base(host, port)
    {}

    // some extra methods
}

FxCop ではまだ警告が表示されません。ctcの処分が適切に処理されていないように見えるので、これはちょっと驚きです。

4

3 に答える 3

2

A1) アンマネージド リソースがない場合は、クラスにファイナライザーを追加しないでください。ファイナライザーは、管理されていないリソースをクリーンアップするのに役立ちます。GC はマネージド リソースを単独で問題なく処理します。

A2) SuppressFinalize は、オブジェクトのガベージ コレクションを妨げません。GC がオブジェクトのファイナライザーを呼び出すのを止めるだけです。ボックス化されていない int は、値の型であるため、ガベージ コレクションされることはありません。文字列は通常どおりガベージ コレクションされます。

A3) Dispose は Dispose セマンティクスを持つことが保証されているため、Close ではなく Dispose を呼び出しますが、Close は少し異なることを行う可能性があります。

A4) 派生クラスが破棄の新しい要件を追加しない場合は、Dispose メソッドをオーバーライドしないでください。

A5) 基底が抽象クラスでも構いません。

A6) FXCop については、答えるのに十分な知識がありません。申し訳ありません。

また、フィールドを null に設定する理由はありません。たとえば、管理されていないリソースがない場合、Dispose メソッドは次のようになります (編集: 質問にリンクされている FXCop ページを読み直して、この場合はクラスを封印する必要があることを追加します)。

public void Dispose() 
{ 
    if (ns != null) 
    { 
        ns.Dispose(); 
    } 
    if (tc != null) 
    { 
        tc.Dispose(); 
    } 
} 

ただし、クラスに管理されていないリソースを保持する派生型がある場合は、例からいくつかの変更を加えて、従来のパターンに固執する必要があります。

protected virtual void Dispose(bool disposing)         
{         
    if (disposing)         
    {         
        if (ns != null)         
        {         
            ns.Dispose();         
        }         
        if (tc != null)         
        {         
            tc.Dispose();         
        }         
    }         
}         

public void Dispose()         
{         
    Dispose(true);         
    GC.SuppressFinalize(this);         
}         
于 2012-10-12T16:43:43.960 に答える
0

IDisposable インターフェイス ( Dispose Pattern ) を実装する基本クラスにファイナライザーを実装することを検討する必要があります。

IDisposable インターフェイスは、ネイティブ リソースを解放するために使用されます。Int32またはString管理されたリソースであり、GC によって収集されます。

クラスがアンマネージ/ネイティブ リソースを使用している場合、基本クラスが抽象クラスか具象クラスかは関係ありません。

派生クラスが新しいリソースを定義していなくても、クラスが基本クラスの機能を継承している場合でも、これは派生クラス オブジェクトがネイティブ リソースを使用することを意味します。派生クラスでのファイナライザーの宣言をスキップしても、基底クラスでファイナライザーが定義されている場合でも、基底クラスのファイナライザーは、GC がメモリ コレクション中にファイナライザーを実行することを示すのに十分です。

GC.SuppressFinalizeF-Reachable キューからエントリを削除し、GC が最初のスキャンでオブジェクト メモリを収集するのに役立つため、呼び出しても問題ありません (実際には呼び出しが必要です) 。

于 2012-10-12T16:46:23.457 に答える
0

Q1: はい。

Q2: いいえ。それらは 100% マネージド型であり、GC が処理します。IDisposable継承または構成のどこかで、管理されていないリソースを破棄する必要がある型用です。など。tc_ns

Q3: お電話くださいDispose()。これは慣用的であり、適切な実装では独自の を呼び出しますClose()

Q4: いいえ、オーバーライドは必要ありません。GC を抑制している場所はどこにもありません。すでに実行しているため、GC がファイナライザーDispose()を実行するのを抑制しています。

Q5: Q4 と変わらない。

Q6: ええ、FxCop のルールに関しては、偽陽性と偽陰性がありIDisposableます。ベスト プラクティスに従い、FxCop から怪しいと思われるものを無視すれば問題ありません。

于 2012-10-12T16:45:32.523 に答える