2009-03-28 7 views
1

誰も私の予想通りに次のコードが動作しない理由を教えていただけますか?私はStreamReaderの周りにIEnumberableラッパーを記述しようとしていますが、ElementAtを使用すると、ElementAtに渡すインデックスに関係なくストリームから連続した文字が読み込まれます。C#3.0 ElementAtはイテレーター関数で壊れていますか?

ファイル "test.txt"には "abcdefghijklmnopqrstuvwxyz"が含まれています。代わりに、私は

とArgumentOutOfRange ABCDEFGHIJKLMNOPQRSTUVWXYZ

を取得...

aaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbb

を:私は出力があることを期待します例外は、私がこれまでにElementAtに渡された唯一のインデックスは0

MSDNが言うされていても、呼び出されます:(> <(T>の))

ソースの種類がIListの<を実装している場合その実装は、指定されたインデックスの要素を取得するために使用されます。それ以外の場合、このメソッドは指定された要素を取得します。

次の要素を取得する」と読みますか?もしそうなら、ちょっと怠惰リストの目的に反していること...

static IEnumerable<char> StreamOfChars(StreamReader sr) 
    { 
     while (!sr.EndOfStream) 
      yield return (char)sr.Read(); 
    } 


    static void Main(string[] args) 
    { 
     using (StreamReader sr = new StreamReader("test.txt")) 
     { 
      IEnumerable<char> iec = StreamOfChars(sr); 

      for (int i = 0; i < 26; ++i) 
      { 
       for (int j = 0; j < 27; ++j) 
       { 
        char ch = iec.ElementAt(i); 
        Console.Write(ch); 
       } 
       Console.WriteLine(); 
      } 
     } 
    } 

答えて

1

はい、MSDNのドキュメントには、「次の要素を取得し、」お読みください。明らかにiecオブジェクトにはIListが実装されています。IEnumerableしか実装していませんので、ランダムな読み込みはできません(もちろん、拡張メソッドや列挙子を使ってランダムなインデックスに到達することはできません)。唯一の利用可能なオプションは転送専用です。

ElementAtメソッドの逆アセンブルされたコードを見てみましょう。明らかに、ソースコレクションがIListを実装していない場合、列挙子で現在の項目を取得します。

public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, int index) 
{ 
    TSource current; 
    if (source == null) 
    { 
     throw Error.ArgumentNull("source"); 
    } 
    IList<TSource> list = source as IList<TSource>; 
    if (list != null) 
    { 
     return list[index]; 
    } 
    if (index < 0) 
    { 
     throw Error.ArgumentOutOfRange("index"); 
    } 
    using (IEnumerator<TSource> enumerator = source.GetEnumerator()) 
    { 
    Label_0036: 
     if (!enumerator.MoveNext()) 
     { 
      throw Error.ArgumentOutOfRange("index"); 
     } 
     if (index == 0) 
     { 
      current = enumerator.Current; 
     } 
     else 
     { 
      index--; 
      goto Label_0036; 
     } 
    } 
    return current; 
} 
関連する問題