C# 我是否需要考虑任何iQualdablt的处理?T>;我用什么?
最近有人向我指出,各种Linq扩展方法(如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实现的事实
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
}
}