7

次のコードを使用して、myClass が foreach を使用できるようにします。しかし、私はプログラミングにかなり慣れていないため、次のコードを理解するのが少し困難です。コメントで私の問題を説明しました。いくつかの情報を提供していただければ幸いです。

    public class MyClass : IEnumerable<string> 
    {  
    //1) What is IEnumerator for?
        // Whats the difference between IEnumerator and IEnumerable
    public IEnumerator<string> GetEnumerator()     
    {
             yield return "first";         
             yield return "second";     
    }      
    //2) What is it for?  It just calls above method 
   IEnumerator IEnumerable.GetEnumerator()
         {
             return GetEnumerator(); 
         } 
    }
   //3) Lastly what benefits I have from implementing genetic interface 
   //IEnumerable<string> instead of just IEnumerable
4

7 に答える 7

12

IEnumeratorとIEnumerableの違いは何ですか?

ジェイソンの答えは良いですが、私はこれについて私がどう思うかを追加したいと思いました。あなたがシーケンスを持っていると想像してください:

1, 1, 2, 3, 5, 8, 13, ...

ここで、そのシーケンスのある位置を指す矢印があると想像してください。

1, 1, 2, 3, 5, 8, 13, ...
         ^

「矢印」は、2つのことを実行できるオブジェクトです。まず、それはあなたにそれが指しているものを与えることができます。第二に、それはそれ自体が次のことを指し示すことができます。

IEnumeratorは矢印です。それはあなたにそれが指しているものを与えるプロパティ、Currentを持っています。これには、MoveNext()というメソッドがあり、それ自体が次のことを指し示します。

そもそもどうやって矢を手に入れるの?アローファクトリーが必要です。工場に矢印を要求すると、シーケンスの最初の要素を指す矢印が表示されます。

IEnumerableは矢印ファクトリです。これには、シーケンスの最初の要素への矢印を提供するGetEnumeratorメソッドがあります。

このスキームの優れた特性は、同じシーケンス内の異なる場所を指す複数の矢印を持つことができることです。

IEnumerableだけでなくジェネリックインターフェイスIEnumerableを実装する利点は何ですか?

シーケンスが整数であると仮定します。あなたが実装するIEnumerable場合あなたが言うとき

foreach(int x in mysequence)

実際に行われるのは、シーケンス内のintをオブジェクトに変換し、整数をボックス化してから、すぐにオブジェクトをボックス化解除して整数に戻し、すべての操作に完全に不要なメモリ割り当てを追加することです。コンパイラがシーケンスが整数であることを知っている場合、不要なボクシング操作をスキップできます。

シーケンスが文字列であると仮定します。実装する場合はIEnumerable<string>、次のように言うことができます。

string first = mysequence.First();

そうでなければ、あなたは言わなければなりません

string first = (string)mysequence.First();

これは不要で、エラーが発生しやすくなります。キャストを介して型が文字列であることをコンパイラに指示するのではなく、型システムを使用して型が文字列であることを簡単に保証できます。

于 2010-12-28T22:57:07.773 に答える
6

1) 何IEnumeratorのために?IEnumeratorとはどう違いIEnumerableますか?

IEnumeratorシーケンスを列挙できるメソッドを表すインターフェイスです。IEnumeratorとの違いIEnumerableは、前者はシーケンスを列挙できるオブジェクトのコントラクトを表し、後者は列挙可能なシーケンスであるオブジェクトのコントラクトを表すことです。

public IEnumerator<string> GetEnumerator() {
         yield return "first";         
         yield return "second";     
}      


IEnumerator IEnumerable.GetEnumerator() {
    return GetEnumerator(); 
} 

2) それは何のためですか? 上記のメソッドを呼び出すだけです。

前者はGetEnumerator、コントラクトのメソッドの実装を表しIEnumerable<string>ます。後者はGetEnumerator、コントラクトでのメソッドの明示的な実装を表していIEnumerableます。問題は、両方のコントラクトに名前GetEnumeratorが付けられたメソッドがありますが、戻り値の型が異なるため、メソッドが両方のコントラクトを同時に満たすことができないことです (実装するクラスはas としてIEnumerable<T>も実装する必要があります)。後者は、as を返す賢明な実装である asの実装を呼び出します。IEnumerableIEnumerable<T> : IEnumerableIEnumerable<string>.GetEnumeratorIEnumeratorIEnumerator<string> : IEnumerator

3) 最後IEnumerable<string>に、単にではなく汎用インターフェイスを実装することで得られる利点は何IEnumerableですか?

タイピングが強い。シーケンス内の要素IEnumerable<string>はすべてのインスタンスであることを知っていますがString、それを知らないためIEnumerable、後者の要素をインスタンスにキャストしようとするStringことになる可能性があります。

于 2010-12-28T18:54:39.450 に答える
3

1) IEnumerator とは何ですか?

IEnumerator は、MoveNext() および Current メンバーを持つ実際の作業部分です。

IEnumerator と IEnumerable の違いは何ですか

IEnumerable は、コレクションが GetEnumerator() を持っていることを通知するためのインターフェイスです。

2) [非ジェネリック GetEnumerator] 何のためにあるの? 上記のメソッドを呼び出すだけです

非ジェネリック メソッドは、下位互換性のために存在します。明示的な実装を使用することにより、可能な限り「見えないように」移動されることに注意してください。あなたがしなければならないのでそれを実装し、それを忘れてください。

3) 最後に、IEnumerable だけでなく、遺伝的インターフェイス IEnumerable を実装することで得られる利点

foreachforeach はループ変数を型キャストするため、アドバンテージと一緒に使用する場合は小さいです。varforeach で使用できるようになります。

foreach (var s in myClassInstance)     // needs `IEnumerable<string>` 
foreach (string s in myClassInstance)  // works with  `IEnumerable` as well 

ただし、 IEnumerable<string>他の領域、特に LINQ へのタイプ セーフなインターフェイスも備えています。

MyClass mc = new MyClass ();
string s = mc.FirstOrDefault();
于 2010-12-28T18:54:51.733 に答える
3

これは の宣言ですIEnumerable<T>:

public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

非ジェネリック IEnumerable インターフェイスも実装する必要があります。IEnumerable.GetEnumerator() の実装を省略すると、コンパイル エラーが発生します。これは、ジェネリックがまだ利用できなかった .NET 1.x の時代と、.NET 1.x アセンブリとの相互運用をサポートする必要があった .NET 2.0 の移行期間の残り物です。私たちはそれで立ち往生しています。

于 2010-12-28T19:00:29.247 に答える
0

3番目の質問(なぜジェネリックを使用するのですか?)に関して、ここにいくつかの答えがあります:

安全性とパフォーマンスを向上させるためにジェネリックコレクションを使用する必要がありますか?

つまり、可能な限りジェネリックコレクションを使用してください。

于 2010-12-28T18:44:58.007 に答える
0

GetEnumeratorジェネリックが言語に導入される前から存在していたため、既存のコードを壊さないように、デフォルトのメソッドはジェネリック実装を呼び出します。

汎用列挙を使用すると、クラスのコンシューマーは反復時に各項目を文字列にキャストする必要がありません。

于 2010-12-28T18:41:57.327 に答える