【问题标题】:Disposing an IDisposable in Linq在 Linq 中处理 IDisposable
【发布时间】:2010-06-25 09:27:34
【问题描述】:

(这是对this问题答案的评论的后续)

在我发布它的 18 个月后,有人在 one of my Linq examples 中发现了一个错误,我在方法链的中途使用了 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);

在看到Marc's answer 到我上面提到的问题之后,我想知道是否可以直接重载 Select 扩展方法,但如果我这样做(通过将 Using 重命名为 Select),编译器会尖叫 Select(d =&gt; 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; }
    }
}

【问题讨论】:

    标签: linq extension-methods idisposable


    【解决方案1】:

    像这样?我这里并没有真正改变太多,除了构造函数的用法......

        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 操作。

    【讨论】:

    • 所以我的扩展方法隐藏了内置方法是对的,所以我基本上“破坏”了 Select 用于任何其他目的?我有点希望编译器能够区分。那么您的 SelectMany 是否也有同样的问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    相关资源
    最近更新 更多