在Linq中处置IDisposable [英] Disposing an IDisposable in Linq
问题描述
(这是对我发布它18个月后,有人发现一个错误我的Linq示例中,在方法链中途我使用了一个IDisposable,它永远不会被处理掉.
18 months after I posted it, someone spotted a bug in one of my Linq examples, where I use an IDisposable half way through a method chain, which never gets disposed.
我试图编写一个扩展方法来处理此问题:
I attempted to write an extension method to handle this:
public static IEnumerable<R> Using<T, R>(
this IEnumerable<T> list, Func<T, R> selector) where R : IDisposable
{
foreach(var item in list)
using(var disposable = selector(item))
yield return disposable;
}
var q = Enumerable.Range(0, 10)
.Using(i => new Disposable(i))
.Select(d => d.Id);
看到马克对我上面提到的问题的回答,我想知道是否可以直接重载Select扩展方法,但是如果这样做(通过将Using
重命名为Select
),编译器会发出关于Select(d => d.Id)
的尖叫声,因为There is no implicit conversion from 'string' to 'System.IDisposable'
.
After seeing Marc's answer to the question I referenced above, I wondered if I could overload the Select extension method directly, but if I do (by renaming Using
to Select
), the compiler squeals about Select(d => d.Id)
, because There is no implicit conversion from 'string' to 'System.IDisposable'
.
这是一个测试班...
Here's a test class...
public class Disposable : IDisposable
{
private string _id;
private bool _disposed = false;
public Disposable(int id)
{
Id = id.ToString();
Console.WriteLine("Creating " + Id);
}
public void Dispose()
{
Console.WriteLine("Disposing " + Id);
_disposed = true;
}
public string Id
{
get
{
if(_disposed) throw new Exception("Call to disposed object!");
return _id;
}
set { _id = value; }
}
}
推荐答案
是这样吗?除了构造函数的用法外,我在这里并没有做太多改变.
Like so? I haven't really changed much here, except the constructor usage...
static void Main()
{
var q = from d in System.Linq.Enumerable.Range(0, 10)
select new Disposable(d);
// alternatively:
// var q = System.Linq.Enumerable.Range(0, 10)
// .Select(d => new Disposable(d));
foreach(var item in q)
{
Console.WriteLine("Hi");
}
}
public static IEnumerable<R> Select<T, R>(
this IEnumerable<T> list, Func<T, R> selector) where R : IDisposable
{
foreach (var item in list)
using (var disposable = selector(item))
yield return disposable;
}
但是!这里要注意的是我们不会引入任何冲突的LINQ操作.
However! The thing to watch here is that we don't introduce any conflicting LINQ operations.
这篇关于在Linq中处置IDisposable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!