C# 我是否需要考虑任何iQualdablt的处理?T>;我用什么?

C# 我是否需要考虑任何iQualdablt的处理?T>;我用什么?,c#,linq,ienumerable,dispose,C#,Linq,Ienumerable,Dispose,最近有人向我指出,各种Linq扩展方法(如Where,Select,等等)返回一个IEnumerable,该IEnumerable也恰好是IDisposable。以下计算结果为True new int[2] {0,1}.Select(x => x*2) is IDisposable 我是否需要处理Where表达式的结果 每当我调用一个返回IEnumerable的方法时,我是否(潜在地)接受了在完成后调用dispose的责任 不,你不必担心这个 它们返回一个IDisposable实现的事实

最近有人向我指出,各种Linq扩展方法(如
Where
Select
,等等)返回一个
IEnumerable
,该
IEnumerable也恰好是
IDisposable
。以下计算结果为
True

new int[2] {0,1}.Select(x => x*2) is IDisposable
我是否需要处理
Where
表达式的结果


每当我调用一个返回
IEnumerable
的方法时,我是否(潜在地)接受了在完成后调用dispose的责任

不,你不必担心这个

它们返回一个
IDisposable
实现的事实是一个实现细节——这是因为C#编译器的Microsoft实现中的迭代器块碰巧创建了一个实现
IEnumerable
IEnumerator
的单一类型。后者扩展了IDisposable
,这就是您看到它的原因

演示这一点的示例代码:

using System;
using System.Collections.Generic;

public class Test 
{
    static void Main() 
    {
        IEnumerable<int> foo = Foo();
        Console.WriteLine(foo is IDisposable); // Prints True
    }

    static IEnumerable<int> Foo()
    {
        yield break;
    }
}

(当然,一个
foreach
循环将自动执行此操作。)

因此,如果我不显式使用枚举器,我永远不需要dispose?有趣的是,在调用了
GetEnumerator()
至少一次的interator上调用
dispose
将使第一次调用返回的枚举器无效,但不是后续调用返回的任何枚举数;在第一次调用
GetEnumerator()
之前调用
Dispose
没有任何效果。@JonSkeet您对
supercat
描述的奇怪行为有什么见解吗?@ean5533:第一次调用
GetEnumerator()
返回对同一引用的引用;此后,它将创建单独的副本。其思想是在通常情况下只创建一个对象,即只迭代一次。与其在Enumerator.MoveNext()上检查true,不如使用Enumerator.FirstOrDefault()!=无效的这封装了框架所需的处理。这在使用多线程感知集合时是安全的。
using (var enumerator = enumerable.GetEnumerator())
{
    if (!enumerator.MoveNext())
    {
        throw // some kind of exception;
    }
    var value = enumerator.Current;
    while (enumerator.MoveNext())
    {
        // Do something with value and enumerator.Current
    }
}