3

レガシーソースを熟読しているときに、私はこれを見つけました:

DataSet myUPC = new DataSet();
myUPC = dbconn.getDataSet(dynSQL);

Resharperは、その「new Dataset()」部分を正しく「グレーアウト」し、「冗長なイニシャライザーを削除する」ことを推奨していますが、それと同じくらい無害ですか?コンパイラーは、2番目の割り当ての直前に最初のインスタンスを単純に破棄しますか?IOW、最初の割り当ては単に不要ですか、それとも潜在的に有害ですか?

4

6 に答える 6

11

コンパイラーは、2番目の割り当ての直前に最初のインスタンスを単純に破棄しますか?

いいえ、ここには自動廃棄はありません。

IOW、最初の割り当ては単に不要ですか、それとも潜在的に有害ですか?

それは2つの小さな点で有害です:

  • これにより、初期化コードとガベージコレクターの両方でより多くの作業が可能になります。重要である可能性は低いですが、そこにあります。コンストラクターがより深刻な可能性のあるネイティブリソースを取得した場合。
  • これにより、コードは実際には実行したくないことを実行したいように見えます。新しい空を作成したくないのにDataSet、なぜそうするのですか?

本当に必要な値で変数を初期化するだけです。

DataSet myUPC = dbconn.getDataSet(dynSQL);

これで、コードはあなたがやりたいことを正確に示します。(メソッド名は、.NETの命名規則に従うように修正します。気を付けてください。)

于 2013-02-25T22:31:21.930 に答える
4

通常は不要です。

DataSetコンストラクターが長時間実行されるバックグラウンドスレッドを開始した場合、または冗長オブジェクトがガベージコレクションされるまで存続する大量のメモリを割り当てた場合にのみ、積極的に有害になります。これは瞬時ではありません。

ただし、礼儀正しいコンストラクターはこれらのことを行うべきではないので、おそらく安全です。ただし、Jon Skeetが指摘しているように、これを見るたびに注意してコードを修正します。これにより、使用する意図のないオブジェクトの作成と破棄がコードに不要になり、コードが欠落しているように見えます。 。

于 2013-02-25T22:31:09.300 に答える
3

IOW、最初の割り当ては単に不要ですか、それとも潜在的に有害ですか?

最初の割り当ては不要ですが、タイプによっては有害である可能性もあります。最初のインスタンスはGCの対象になりますが、(理由もなく)初期化され、使用されることはありません。

于 2013-02-25T22:30:53.437 に答える
1

はい、他の回答で示されているように、実際には多少有害です。これは主に、使用されることのないオブジェクトを割り当て、最終的にガベージコレクションする必要があるためです。しかし、もう少し詳しく説明します。

最初のインスタンスを破棄できますか?

  DataSet myUPC = new DataSet();
  myUPC = dbconn.getDataSet(dynSQL);

コンパイラーは、2番目の割り当ての直前に最初のインスタンスを単純に破棄しますか?

新しい未使用のインスタンスを収集するGC(ガベージコレクター)を破棄することを意味すると仮定すると、答えは次ようになります。詳細を説明させてください。

GCは、ヒープがすぐにいっぱいになるときや、ヒープの残りのスペースに収まらないオブジェクトを割り当てようとするときなど、いつでも実行できます。したがって、GCは(偶然に)最初のステートメントと2番目のステートメントの間で正確に実行される場合もあります。new DataSet()ただし、ローカル変数にオブジェクトへの参照があるため、これはオブジェクトを収集しませんmyUPC。オブジェクトへの参照がない場合にのみ、オブジェクトはコレクションの対象と見なされます1

1)実際には、オブジェクトは、いわゆるルートからオブジェクトへの参照のチェーンがない場合にのみコレクションの対象と見なされます。ルートには、静的フィールド、メソッド引数、ローカル変数、および評価スタックが含まれます。

コンストラクター呼び出しを最適化できますか?

DataSet myUPC; /* Optimized away? */
myUPC = dbconn.getDataSet(dynSQL);

また、Just-In-Timeコンパイラーは、初期化されるオブジェクト以外のものに影響を与える可能性があるため(つまり、副作用があるため)、コンストラクター呼び出しを単純に最適化することはできません。たとえば、コンパイラーがコンストラクター呼び出しを最適化した場合、コンストラクターはコンソールに何も出力しません。これは望ましくないか予期されていないため、コンストラクター呼び出しはそこにとどまり、新しいインスタンスを生成する必要があります。

class MyClass
{
    public MyClass()
    {
        Console.WriteLine("Constructor called!");
    }
}

abstract class X
{
    void Do()
    {
        MyClass my = new MyClass();  // Should always print "Constructor called!"
        my = GetMyClass();
        // ...
    }

    protected abstract MyClass GetMyClass();
}
于 2013-02-26T01:03:16.803 に答える
1

他に参照がないため、ガベージコレクションが行われるまでぶらぶらします。ただし、コンストラクターに副作用がある場合(おそらくDataSetのコンストラクターには副作用がない場合)、それも有害である可能性があります。

于 2013-02-25T22:31:21.830 に答える
1

myUPCは、dbconn.getDataSet()の出力で上書きされます。これは、getDataSet()がファクトリメソッドであり、Dataset型のオブジェクトを返すためです。

于 2013-02-25T22:31:29.127 に答える