6

我很想知道该SingleOrFallback方法是如何在MoreLinq中实现的,并发现了一些我以前从未见过的东西:

    public static T SingleOrFallback<T>(this IEnumerable<T> source, Func<T> fallback)
    {
        source.ThrowIfNull("source");
        fallback.ThrowIfNull("fallback");
        using (IEnumerator<T> iterator = source.GetEnumerator())
        {
            if (!iterator.MoveNext())
            {
                return fallback();
            }
            T first = iterator.Current;
            if (iterator.MoveNext())
            {
                throw new InvalidOperationException();
            }
            return first;
        }
    }

为什么IEnumerator<T>using声明中?foreach这也是在使用on an时应该考虑的事情IEnumerable<T>吗?

附带问题:这种方法究竟做了什么?每当源序列不包含一个项目时,它是否返回后备项目?

4

2 回答 2

11

IEnumerator<T>extends IDisposable,所以你应该在 using 语句中使用它。foreach自动执行此操作。(非泛型IEnumerator 不会扩展IDisposable,但 C# 编译器仍会生成Dispose有条件调用的代码。这是 C# 1.0 和 1.2 之间的(少数)更改之一,其中 1.2 是 .NET 1.1 附带的版本,出于某种原因。 )

这是一篇文章,解释了为什么这在迭代器块的上下文中很重要。

至于该方法的作用:

  • 如果序列为空,则返回后备项
  • 如果序列只有一项,则返回它
  • 如果序列有多个项目,则抛出异常

PS:很高兴看到 MoreLinq 得到了一些关注 :)

于 2009-06-02T10:45:42.640 回答
0

如果不调用 Dispose,一些枚举器的行为会很糟糕;这对于非泛型代码和泛型代码一样正确(非泛型代码要求代码要么对 Dispose 调用进行鸭式输入,要么强制转换为 IDisposable,然后调用 IDisposable.Dispose)。确保 IEnumerator 对象被释放是一种好的习惯;我认为任何接受未知类型的 IEnumerable 的例程的正确性都是必要的。

于 2011-04-03T18:04:44.357 回答