この記事では、foreachの機能について簡単に説明します。 最初の瞬間を知っている可能性が最も高く、2番目の瞬間を知っていない可能性が高くなります。
配列に関する以前の記事最初の瞬間
インタビューでは、「クラスを
foreach
動作させるには何をする必要がありますか?」 この質問に対する答えは通常、次のように聞こえます-"
IEnumerable
"。 この答えは正しいですが、完全ではありません。 原則として、インタビューでのこの回答は十分であり、私はそれを間違っていると考える人に会ったことがありません。 実際、
foreach
は
ダックタイピングを使用し
ます 。 クラスを
foreach
、
MoveNext
メソッドと
Current
プロパティを持つものを返す
GetEnumerator
メソッドを用意すれば十分
GetEnumerator
。
間違ったクラスを
foreach
スリップさせた場合、これらのメソッドを覚えておく必要はありません。コンパイラは、このクラスに欠けているものを正確に教えてくれます。
例
foreach
テストします。
class Program { static void Main(string[] args) { var container = new Container(); foreach (var item in container) { } } }
間違ったコンテナ:
public class Container { }
コンパイラエラー:
foreach statement cannot operate on variables of type 'Container' because 'Container' does not contain a public definition for 'GetEnumerator'
GetEnumerator
メソッドをコンテナおよび列挙子クラスに追加します。
正しいコンテナ:
public class Container { public Enumerator GetEnumerator() { return new Enumerator(); } }
不正な列挙子:
public class Enumerator { }
コンパイラエラー:
foreach requires that the return type 'Enumerator' of 'Container.GetEnumerator()' must have a suitable public MoveNext method and public Current property
MoveNext
メソッドと
Current
プロパティを列挙子に追加します。
正しい列挙子:
public class Enumerator { public bool MoveNext() { return false; } public object Current { get { return null; } } }
これでコンパイラは問題ありません。
注:
Current
プロパティは、 ref type
とvalue type
両方の任意の型を返すことができvalue type
。 実際、これが、不要なboxing
とunboxing
を回避するために、 generics
がないときにアヒルタイピングを使用する理由でした。第二の瞬間
インタビューでは、
IDisposable
に関する質問があり、手動のリソース管理に関する一般的な質問に加えて、コンパイラが
Dispose
メソッドを自動的に呼び出すことができる時期についての質問があります。 答えはわかっています
Dispose
using()
ステートメントを使用すると、
Dispose
が自動的に呼び出されます。 この答えは正しいですが、不完全です!
Dispose
メソッドは、
using()
に加えて、列挙子が
IDisposable
実装している場合、列挙子の
foreach
で呼び出される2つの場合に
Dispose
ことができます。
例
Dispose
を使用する
Dispose
:
using System; public class Enumerator : IDisposable { public bool MoveNext() { return false; } public object Current { get { return null; } } public void Dispose() { Console.WriteLine("Dispose"); } }
この例を実行すると、コンソールに「Dispose」行が表示されます。
興味のある方のために、ここにコンパイラが私たちのケースのために生成するコードがあります:
Container container = new Container(); Enumerator enumerator = container.GetEnumerator(); try { while (enumerator.MoveNext()) { var element = enumerator.Current;
ご清聴ありがとうございました!