(这是对答案的评论的后续this https://stackoverflow.com/questions/1751153/how-do-you-dispose-of-idisposableobject-create-inside-of-a-linq-expression问题)
在我发布 18 个月后,有人发现了一个错误我的 Linq 示例之一 https://stackoverflow.com/questions/21280/am-i-missing-something-about-linq/80709#80709,我在方法链的中间使用了 IDisposable,它永远不会被释放。
我尝试编写一个扩展方法来处理这个问题:
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);
看到后马克的回答 https://stackoverflow.com/questions/1751153/how-do-you-dispose-of-idisposableobject-create-inside-of-a-linq-expression/1751277#1751277对于我上面提到的问题,我想知道是否可以直接重载 Select 扩展方法,但如果我这样做(通过重命名Using
to Select
),编译器会发出尖叫声Select(d => d.Id)
, 因为There is no implicit conversion from 'string' to 'System.IDisposable'
.
这是一个测试课...
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; }
}
}
像这样吗?除了构造函数的用法之外,我在这里并没有真正改变太多......
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 操作。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)