是C#3.0的ElementAt打破了迭代器的功能呢?
-
22-08-2019 - |
题
谁能告诉我,为什么下面的代码不工作,我所期望的方式?我试图写围绕一个StreamReader一个IEnumberable包装,但是当我使用的ElementAt就可以了,它读取连续字符从流无论我传递给ElementAt的索引。
在文件 “的test.txt” 包含 “ABCDEFGHIJKLMNOPQRSTUVWXYZ”。我期望的输出是:
aaaaaaaaaaaaaaaaaaaaaaaaaaa结果 bbbbbbbbbbbbbbbbbbbbbbbbbbb结果 ...
相反,我得到
ABCDEFGHIJKLMNOPQRSTUVWXYZ
和ArgumentOutOfRangeException被调用,即使我传递给ElementAt的迄今唯一索引为0。
MSDN表示:
如果源的类型实现IList <(中<(T>)>),即执行用于获得指定索引处的元素。否则,此方法获得指定的元素。
应该读取 “获得的下元素”?如果是这样,这有点儿违背了懒惰名单的目的...
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();
}
}
}
解决方案
是,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;
}
不隶属于 StackOverflow