【问题标题】:Is C# 3.0 ElementAt broken for iterator functions?C# 3.0 ElementAt 是否因迭代器函数而损坏?
【发布时间】:2009-03-28 08:31:34
【问题描述】:

谁能告诉我为什么下面的代码不能按我预期的方式工作?我正在尝试围绕 StreamReader 编写一个 IEnumberable 包装器,但是当我在其上使用 ElementAt 时,无论我传递给 ElementAt 的索引如何,它都会从流中读取顺序字符。

文件“test.txt”包含“abcdefghijklmnopqrstuvwxyz”。我希望输出是:

呸呸呸呸呸呸呸呸呸
bbbbbbbbbbbbbbbbbbbbbbbbbbbbb
...

我得到了

abcdefghijklmnopqrstuvwxyz

并且 ArgumentOutOfRangeException 被调用,尽管到目前为止我传递给 ElementAt 的唯一索引是 0。

MSDN 说:

如果源的类型实现了 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();
            }
        }
    }

【问题讨论】:

    标签: c# linq streamreader


    【解决方案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;
    }
    

    【讨论】:

      猜你喜欢
      • 2019-01-22
      • 2021-07-15
      • 1970-01-01
      • 2013-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-01
      • 1970-01-01
      相关资源
      最近更新 更多