4

次のコードは、using(...)機能/目的を無関係にしますか?
GC のパフォーマンスが低下する可能性はありますか?

class Program
{
    static Dictionary<string , DisposableClass> Disposables
    {
        get
        {
            if (disposables == null)
                disposables = new Dictionary<string , DisposableClass>();

            return disposables;
        }
    }

    static Dictionary<string , DisposableClass> disposables;

    static void Main(string[] args)
    {
        DisposableClass disposable;
        using (disposable = new DisposableClass())
        {
            //  do some work
            disposable.Name = "SuperDisposable";
            Disposables["uniqueID" + Disposables.Count] = disposable;
        }

        Console.WriteLine("Output: " + Disposables["uniqueID0"].Name);

        Console.ReadLine();
    }
}

class DisposableClass : IDisposable
{
    internal string Name
    {
        get { return myName; }
        set { myName = value; }
    }

    private string myName;

    public void Dispose( )
    {
        //throw new NotImplementedException();
    }
}

出力: SuperDisposable

この機能についての私の理解は、 のusing(...)破棄を直ちに強制することDisposableClassです。ただし、コード ブロック内では、クラスをディクショナリ コレクションに追加しています。私の理解では、クラスは本質的に参照型です。したがって、私の実験は、この方法でコレクションに追加された使い捨てオブジェクトに何が起こるかを確認することでした。

この場合DisposableClass、まだかなり生きています。クラスは参照型であるため、コレクションは単にこの型を参照するのではなく、実際にクラスを値として保持していると仮定しました。しかし、それも意味がありませんでした。

それで、実際に何が起こっているのですか?

編集:いくつかの回答で示唆されているように、オブジェクトが死んでいないことを証明するために出力を含むコードを修正しました。

2番目の編集:さらにコードを調べたときに、これがどうなるかは次のとおりです。

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

    private void Dispose(bool dispose)
    {
        if (!isDisposed)
        {
            if (dispose)
            {
                // clean up managed objects
            }

            //  clean up unmanaged objects
            isDisposed = true;
        }
    }

    ~DisposableClass( )
    { Dispose(false); }

メソッドに渡されるコード ( にブレークポイントがありましたprivate void Dispose(bool dispose)) をステップ実行falseすると、ここでリソースを適切に破棄することが不可欠になります。とにかく、クラスはまだ生きていますが、間違いなく例外を設定しています。答えは私をより興味深くしました...

4

4 に答える 4

11

オブジェクトを破棄しても破棄されません。使用している管理されていないリソースが不要になったときにクリーンアップするように指示するだけです。あなたの例では、使い捨てオブジェクトを作成し、辞書に割り当ててから、いくつかのリソースを削除するように指示しています。

このステートメントの正しいシナリオはusing、リソースを初期化し、それを使って何かを行い、それを破棄して忘れる場合です。例えば:

using (var stream = new FileStream("some-file.txt"))
using (var reader = new StreamReader(stream))
{
    Console.Write(reader.ReadToEnd());
}

使用後にオブジェクトを保持したい場合は、オブジェクトを破棄すべきではusingないため、ステートメントを使用しないでください。

于 2010-02-13T23:11:08.920 に答える
2

usingブロックが終了した後にオブジェクトが必要になるため、この場合はブロックを使用しないでください。オブジェクトの有効期間の開始点と終了点が明確な場合にのみ使用してください。

于 2010-02-13T23:09:11.100 に答える
2

IDisposable は少し特殊なインターフェイスですが、それでもインターフェイスであることを覚えておくことが重要です。using ブロックが終了すると、オブジェクトで Dispose() が呼び出されます。これ以上何もない。参照は引き続き有効であり、Dispose メソッドが何もしない場合、オブジェクトはまったく影響を受けません。破棄を追跡せず、明示的に例外をスローした場合、.NET には固有の破棄状態がないため、その時点以降は例外が発生しません。

于 2010-02-14T00:00:21.440 に答える
1

IDisposableインターフェースは、タイプがある種のリソースを管理することを示します。このDisposeメソッドは、ガベージ コレクションが行われ、リソースがファイナライザーによって解放されるのを待たずに、インスタンスによって使用されるリソースを破棄できるようにするために存在します。

あなたの例では、ディクショナリにはまだ使い捨てクラスへの参照が含まれていますが、インスタンスはusingブロックの最後で破棄されます。その後インスタンスでメソッドを呼び出そうとすると、インスタンスが「動作中」の状態でなくなったことを示すために、ObjectDisposedExceptionまたはがスローされる可能性があります。InvalidOperationException

を破棄するIDisposableことを、インスタンスが占有していたメモリを解放すること、またはそのインスタンスでガベージ コレクション ルーチンを呼び出すことと混同しないでください。インスタンスは、他のものと同様にガベージ コレクターによって追跡および管理され、ガベージ コレクターが決定したときにのみ解放されます。

于 2010-02-13T23:11:29.507 に答える