191

オブジェクトを使い終わったら、すべてのオブジェクトをnull( VB.NET で) に設定する必要がありますか?Nothing

.NET では、インターフェイスを実装するオブジェクトのインスタンスを破棄して一部のリソースを解放することが不可欠であることを理解していますIDisposableが、オブジェクトは破棄された後でも何かになる可能性があります (したがって、isDisposedフォームのプロパティ)。記憶の中で、または少なくとも部分的に?

また、オブジェクトがスコープ外になると、ガベージ コレクターの次のパスに備えてコレクションのマークが付けられることも知っています (ただし、これには時間がかかる場合があります)。

したがって、これを念頭に置いnullて、システムがメモリを解放する速度を上げるように設定します。これは、メモリが範囲外であることを解決する必要がなく、悪い副作用があるからですか?

MSDN の記事では例としてこれを行うことはありません。現在、害が見られないため、これを行っています。ただし、さまざまな意見が混在しているため、コメントは役に立ちます。

4

15 に答える 15

73

Karlは絶対に正しいので、使用後にオブジェクトをnullに設定する必要はありません。オブジェクトがを実装している場合は、そのオブジェクト( .. 、または、ブロックでラップされている)を使い終わったらIDisposable必ず呼び出してください。ただし、を呼び出すことを忘れた場合でも、オブジェクトのfinaliserメソッドが呼び出す必要があります。IDisposable.Dispose()tryfinallyusing()Dispose()Dispose()

私はこれが良い治療法だと思いました:

IDisposableを掘り下げる

この

IDisposableを理解する

GCは自己調整型で不透明であるため、GCとその管理戦略を2番目に推測しようとしても意味がありません。Dot NetRocksでのJeffreyRichterとの内部動作については、ここで良い議論がありました。WindowsメモリモデルのJeffrey RichterとC#第20章を介したRichtersの本CLRは、すばらしい扱いを受けています。

于 2008-08-05T20:56:28.667 に答える
37

オブジェクトを使い終わったときにオブジェクトを null に設定しないようにするもう 1 つの理由は、実際にはオブジェクトをより長く存続させることができるからです。

例えば

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is now eligible for garbage collection         

    // ... rest of method not using 'someType' ...
}

「DoSomething」の呼び出し後に someType によって参照されるオブジェクトを GC できるようにしますが、

void foo()
{
    var someType = new SomeType();
    someType.DoSomething();
    // someType is NOT eligible for garbage collection yet
    // because that variable is used at the end of the method         

    // ... rest of method not using 'someType' ...
    someType = null;
}

メソッドが終了するまでオブジェクトを存続させる場合があります。通常、JIT は null への割り当てを最適化するため、コードの両方のビットが同じになります。

于 2008-08-15T14:43:34.930 に答える
13

いいえ、オブジェクトを null にしないでください。https://web.archive.org/web/20160325050833/http://codebetter.com/karlseguin/2008/04/28/foundations-of-programming-pt-7-back-to-basics-を確認できます。詳細についてはmemory/を参照してください。ただし、null に設定しても、コードを汚す以外は何もしません。

于 2008-08-05T20:23:33.477 に答える
7

一般に、使用後にオブジェクトをnullにする必要はありませんが、場合によっては、それが良い習慣だと思います。

オブジェクトがIDisposableを実装し、フィールドに格納されている場合は、破棄されたオブジェクトの使用を避けるために、それをnullにするのが良いと思います。次の種類のバグは苦痛を伴う可能性があります。

this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();

フィールドを破棄した後でフィールドをnullにし、フィールドが再び使用される行でNullPtrExを取得することをお勧めします。そうしないと、(DoSomethingの機能によっては)不可解なバグが発生する可能性があります。

于 2008-08-09T11:16:04.837 に答える
7

null変数の必要性を感じた場合、コードが十分に厳密に構造化されていない可能性があります。

変数のスコープを制限する方法はいくつかあります。

スティーブ・トランビーが述べたように

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of

同様に、中括弧を使用するだけです。

{
    // Declare the variable and use it
    SomeObject object = new SomeObject()
}
// The variable is no longer available

「見出し」なしで中括弧を使用すると、コードが実際にクリーンアップされ、理解しやすくなります。

于 2008-08-09T12:13:12.553 に答える
6

また:

using(SomeObject object = new SomeObject()) 
{
  // do stuff with the object
}
// the object will be disposed of
于 2008-08-05T20:37:30.063 に答える
5

変数をnullに設定する必要があるのは、変数がスコープ外にならず、それに関連付けられたデータが不要になった場合のみです。それ以外の場合は必要ありません。

于 2008-08-05T20:32:48.153 に答える
5

通常、null に設定する必要はありません。しかし、クラスにリセット機能があるとします。

Dispose の一部が正しく実装されておらず、System.ObjectDisposed 例外がスローされる可能性があるため、dispose を 2 回呼び出したくないため、そうすることもできます。

private void Reset()
{
    if(_dataset != null)
    {
       _dataset.Dispose();
       _dataset = null;
    }
    //..More such member variables like oracle connection etc. _oraConnection
 }
于 2012-04-17T08:55:49.503 に答える
3

この種の「使用後にオブジェクトを null に設定する必要はありません」は完全に正確ではありません。破棄した後に変数を NULL にする必要がある場合があります。

.Dispose()はい、完了したら、常にまたはそれがあるものに電話する必要.Close()があります。ファイル ハンドル、データベース接続、使い捨てオブジェクトなどです。

それとは別に、LazyLoad の非常に実用的なパターンがあります。

を持っていてインスタンス化ObjAしたとしますclass A。 ofClass Aというパブリック プロパティがあります。PropBclass B

内部的にPropBは、のプライベート変数を使用し、_Bデフォルトは null です。が使用されると、が nullPropB.Get()かどうかをチェックし、そうであれば、 a を にインスタンス化するために必要なリソースを開きます。その後、 を返します。_PropBB_PropB_PropB

私の経験では、これは非常に便利なトリックです。

null が必要になるのは、 A の内容が_PropBの以前の値の子であるような方法で A をリセットまたは変更した場合です。その場合は、 LazyLoad がリセットして正しい値 IF コードを取得できるようAに、Dispose と null を出力する必要があります。_PropBが必要です。

_PropB.Dispose()LazyLoad の null チェックが成功することを期待するだけの場合は、null にはならず、古いデータが表示されます。Dispose()実際には、念のために後で null にする必要があります。

そうでないことを願っていますが、現在、この動作を示すコードがあり、Dispose を実行しDispose()_PropB呼び出し関数の外側で (したがって、ほとんどスコープ外です)、プライベート prop はまだ null ではありません。古いデータがまだ残っています。

最終的に、破棄されたプロパティは無効になりますが、それは私の観点からは非決定論的です。

dbkk がほのめかしているように、主な理由は、親コンテナー ( ObjAwith PropB)_PropBDispose().

于 2012-04-11T01:12:07.903 に答える
1

参照をnullにすることが理にかなっている場合があります。たとえば、優先キューのようにコレクションを作成している場合、契約により、クライアントがそれらのオブジェクトをキューから削除した後、それらのオブジェクトをクライアントのために存続させてはなりません。

しかし、この種のことは、長寿命のコレクションでのみ重要です。キューが作成された関数の最後まで存続しない場合は、それほど重要ではありません。

全体として、あなたは本当に気にするべきではありません。コンパイラとGCにそれぞれの仕事を任せて、あなたが自分の仕事をできるようにします。

于 2008-08-05T20:46:08.033 に答える
1

この記事もご覧ください: http://www.codeproject.com/KB/cs/idisposable.aspx

ほとんどの場合、オブジェクトを null に設定しても効果はありません。必ずそうする必要があるのは、サイズが 84K を超える「ラージ オブジェクト」(ビットマップなど) を操作している場合のみです。

于 2008-08-17T04:46:54.057 に答える
0

GC 実装者の設計により、無効化で GC を高速化することはできないと思います。彼らは、GC がどのように/いつ実行されるかについて、あなたが心配しないことを望んでいると確信しています。GC は、どこにでもある、あなたを保護し、見守っている存在のように扱ってください. .

個人的には、自己文書化の形式として変数を使い終わったときに、変数を明示的に null に設定することがよくあります。宣言して使用し、後で null に設定するのではなく、不要になった直後に null にします。私ははっきりと、「私は正式にあなたとの仕事を終えました...いなくなって...」と言っています。

GC された言語で無効化は必要ですか? いいえ、GC に役立ちますか? はい、多分いいえ、確かにわかりません。設計上、私は本当にそれを制御できません。このバージョンまたはそのバージョンでの今日の回答に関係なく、将来のGC実装は私の制御を超えて回答を変更する可能性があります. さらに、ヌル化が最適化されているかどうかは、必要に応じて派手なコメントにすぎません。

それが私の足跡をたどる次の愚かな愚か者に私の意図をより明確にするかどうか、そしてそれが時々GCを助ける可能性があるなら、それは私にとって価値がある. ほとんどの場合、私はきちんと整理された気分になり、Mongo は整理整頓された気分になるのが好きです。:)

私はそれを次のように見ています: プログラミング言語は、人々が他の人に意図のアイデアを与え、コンパイラに何をすべきかという仕事の要求を与えるために存在します.コンパイラはその要求をCPU用の別の言語(時には複数の言語)に変換します. CPU は、使用した言語、タブ設定、コメント、文体の強調、変数名などを大騒ぎする可能性があります。CPU は、どのレジスター、オペコード、およびメモリ位置を調整するかを伝えるビット ストリームに関するすべてです。コードで記述された多くのことは、指定した順序で CPU によって消費されるものに変換されません。私たちの C、C++、C#、Lisp、Babel、アセンブラなど、現実ではなく理論であり、作業明細書として書かれています。アセンブラー言語でさえ、あなたが見るものはあなたが得るものではありません。

「不要なもの」(空白行など)は「ノイズであり、コードを乱雑にするだけである」という考え方を理解しています。それは私のキャリアの初期の私でした。私はそれを完全に理解しています。この時点で、私はコードをより明確にする方向に傾いています。プログラムに「ノイズ」を 50 行も追加しているわけではありません。あちこちに数行あります。

どんな規則にも例外があります。揮発性メモリ、静的メモリ、競合状態、シングルトン、「古い」データの使用、およびそのようなすべての腐敗を伴うシナリオでは、それは異なります。メモリは一部ではないため、独自のメモリを管理し、適切にロックおよび無効化する必要があります。 GC'd Universe -- うまくいけば、誰もがそれを理解してくれます。それ以外の場合、GC された言語では、必要性や保証されたパフォーマンスの向上ではなく、スタイルの問題です。

一日の終わりには、GC の対象となるものとそうでないものを理解していることを確認してください。適切にロック、廃棄、および無効化します。ワックスオン、ワックスオフ。息を吸い、息を吐きます。そして、私が言う他のすべてについて:それが気分が良いなら、それをしてください. あなたの走行距離は異なる場合があります...そうあるべきです...

于 2016-05-10T13:07:53.603 に答える
-1

一部のオブジェクトは.dispose()、リソースをメモリから強制的に削除するメソッドを想定しています。

于 2008-08-05T20:21:17.317 に答える