30

C# で foreach ループがどのように機能するかについての基本を知っています (C# で foreach ループがどのように機能する)

foreach を使用するとメモリが割り当てられ、ガベージ コレクションが発生する可能性があるかどうか疑問に思っています。(すべてのビルトイン システム タイプの場合)。

たとえば、System.Collections.Generic.List<T>クラスで Reflector を使用すると、GetEnumerator の実装は次のようになります。

public Enumerator<T> GetEnumerator()
{
    return new Enumerator<T>((List<T>) this);
}

使用するたびに、これは新しい列挙子 (およびより多くのガベージ) を割り当てます。

すべてのタイプがこれを行いますか?もしそうなら、なぜですか?(単一の列挙子を再利用することはできませんか?)

4

4 に答える 4

3

いいえ、リストを列挙してもガベージ コレクションは発生しません。

クラスの列挙子はList<T>、ヒープからメモリを割り当てません。これはクラスではなく構造体であるため、コンストラクターはオブジェクトを割り当てず、値を返すだけです。コードは、そのforeach値をヒープではなくスタックに保持します。

ただし、他のコレクションの列挙子はクラスである場合があり、ヒープにオブジェクトを割り当てます。確実にするには、各ケースの列挙子の型を確認する必要があります。

于 2013-08-31T21:06:31.843 に答える
0

列挙子は現在のアイテムを保持するためです。データベースに比べるとカーソルのようなものです。複数のスレッドが同じ列挙子にアクセスすると、シーケンスを制御できなくなります。また、foreach が参照するたびに最初の項目にリセットする必要があります。

于 2013-08-31T20:53:43.177 に答える
0

コメントで述べたように、これはガベージ コレクションのポイントであるため、通常は心配する必要はありません。そうは言っても、私の理解では、はい、各 foreach ループは新しい Enumerator オブジェクトを生成し、最終的にガベージ コレクションされます。理由については、こちらのインターフェイスのドキュメントを参照してください。ご覧のとおり、次のオブジェクトを要求する関数呼び出しがあります。これを行う能力は、列挙子が状態を持っていることを意味し、次のものを知る必要があります。これが必要な理由については、コレクション アイテムのすべての順列間で相互作用を引き起こしているイメージ:

foreach(var outerItem in Items)
{
   foreach(var innterItem in Items)
   {
      // do something
   }
}

ここでは、同時に同じコレクションに 2 つの列挙子があります。明らかに、場所を共有しても目的は達成されません。

于 2013-08-31T20:56:27.093 に答える