カスタム列挙型/コレクションはいつ便利ですか?
-
05-07-2019 - |
質問
カスタム列挙を使用したリアルタイムの例を理解しようとさまざまなWebサイトにアクセスした後、この行を削除しています。例があります。しかし、それらは私を混乱に導きます。
例
テイク1
class NumberArray
{
public int[] scores;
public NumberArray()
{
}
public NumberArray(int[] scores)
{
this.scores = scores;
}
public int[] Scores
{
get {return scores;}
}
}
テイク2
public class Enumerator : IEnumerator
{
int[] scores;
int cur;
public Enumerator(int[] scores)
{
this.scores = scores;
cur = -1;
}
public Object Current
{
get {
return scores[cur];
}
}
public void Reset()
{
cur = -1;
}
public bool MoveNext()
{
cur++;
if (cur < scores.Length)
return true;
else return false;
}
}
public class Enumerable : IEnumerable
{
int[] numbers;
public void GetNumbersForEnumeration(int[] values)
{
numbers = values;
for (int i = 0; i < values.Length; i++)
numbers[i] = values[i];
}
public IEnumerator GetEnumerator()
{
return new Enumerator(numbers);
}
}
メイン
static void Main()
{
int[] arr = new int[] { 1, 2, 3, 4, 5 };
NumberArray num = new NumberArray(arr);
foreach(int val in num.Scores)
{
Console.WriteLine(val);
}
Enumerable en = new Enumerable();
en.GetNumbersForEnumeration(arr);
foreach (int i in en)
{
Console.WriteLine(i);
}
Console.ReadKey(true);
}
テイク2では、カスタムの反復に従って、同じ整数配列を繰り返し処理しました テイク1.カスタムイテレーションを使用して整数を反復するためにブッシュについてビートする必要があるのはなぜですか?
おそらく、リアルタイムのカスタム反復のニーズを逃しました。既存の反復機能ではできないタスクを説明してもらえますか? (学校教育を終えたばかりなので、簡単に例を挙げて、正しく理解できるようにします)。
更新: これらの例をいくつかのサイトから取りました。そのコードには特別なものは何もありません。カスタム反復を使用しなくても非常に簡単に達成できます。カスタム反復が非常に便利な実際のシナリオを知ることが私の興味でした。
解決
カスタム反復子は、反復するリソースがメモリにプリロードされておらず、各反復で必要に応じて取得される場合に役立ちます。たとえば、LINQ to SQLで次のような操作を行う場合:
foreach(var employee in dataContext.Employees) {
// Process employee
}
foreach
ループの各ステップで、次のレコードを取得するためにデータベース内のEmployeesテーブルが照会されます。このように、ループを早期に終了すると、テーブル全体ではなく、必要なレコードのみが読み取られます。
実際の例についてはこちらをご覧ください:ファイルの行を列挙 。ここで、各行は foreach
ループの各反復でファイルから読み取られます。 (補足として、.NET Framework 4はこれと同じ機能を組み込みで提供しています。)
他のヒント
正直なところ、あなたが何を求めているのか完全にはわかりませんが、配列を返す(テイク1のような)とイテレータを返す(テイク2)の違いが気になるなら、ここに私の答えがあります。
配列を返すこととイテレータを返すことには大きな違いがあります。配列を返すということは、内部状態を返すことを意味します(戻りの一部としてコピーを作成しない限り、それは高価です)。イテレータを返す場合、単に抽象化を返すだけです。これにより、呼び出し側は状態を反復できます。これは、必要に応じて遅延評価を実行できることも意味します(配列を返す場合は明らかにできないことです)。
また、C#2のイテレータのサポートにより、IEnumerableを手動で実装する理由はまったくありません。詳細については、この質問をご覧ください yieldキーワードをわかりやすく説明できますか
過去にカスタム反復が有用だった別の例として、共通の抽象化を提供して、ツリー構造内のすべてのノードを再帰的に列挙することでした...
foreach (Node n in tree)
//...do something