2010-06-25 25 views
4

(這是從一個評論對答案遵循以this問題)Linq中處置的IDisposable的

18個月後我的貼吧,有人在one of my Linq examples,在這裏我使用了IDisposable半發現一個bug通過方法鏈的方式,永遠不會被處置。

我試圖寫一個擴展的方法來處理這個問題:

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到我上面提到的問題,我想,如果我可以直接重載選擇擴展方法,但如果我這樣做(通過重命名爲UsingSelect),編譯器尖叫大約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; } 
    } 
} 

回答

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

+2

所以我是對的,我的擴展方法隱藏內置的一個,所以我基本上是「破」選擇用於任何其他目的?我很希望編譯器能夠分辨出差異。你的SelectMany會有同樣的問題嗎? – Benjol 2010-06-25 11:36:57

相關問題