2009-06-10 45 views
1

我目前在思考一些想法,我無法正確理解。捕獲的變量實例化問題

問題是我想用一個lambda函數來實例化一個捕獲的變量和另一個lambda來訪問該變量的一個屬性。

由於實例化發生在lambda內,所以變量實際上並沒有實例化,我想在第二個lambda內使用它..這是一種雞和蛋問題。

我知道變量將是實例化了它在第二個lambda中使用的時間,但編譯器沒有這樣做。

我的想法有什麼辦法可以工作嗎?下面是實際的代碼:

class Program 
{ 
    static void Main(string[] args) 
    { 
     SqlCommand cmd; 

     using (new DisposableComposite(
      () => cmd = new SqlCommand(), 
      () => cmd.Connection)) // <- compiler error - variable not instantiated 
     { 
      // code 
     } 
    } 
} 

class DisposableComposite : IDisposable 
{ 
    private List<IDisposable> _disposables = new List<IDisposable>(); 

    public DisposableComposite(params Func<IDisposable>[] disposableFuncs) 
    { 
     // ensure the code is actually executed 
     foreach (var func in disposableFuncs) 
     { 
      IDisposable obj = func.Invoke(); 
      _disposables.Add(obj); 
     } 
    } 

    public void Dispose() 
    { 
     foreach (var disposable in _disposables) 
     { 
      disposable.Dispose(); 
     } 
    } 
} 

回答

5

你的意思是隻需添加:

SqlCommand cmd = null; 

(解決了「明確賦值」毛刺;它明確賦值...空;-p我們然後在使用之前更新該值)。

IMO,不過,你會做嵌套using報表更好......這是不明確(從代碼),其中實際的連接從哪兒來?

using(var conn = new SqlConnection(...)) 
using(var cmd = conn.CreateCommand()) { 
    // ... 
} 
+2

該死的..那是一件容易的事。我想我需要另一杯咖啡。 :) – VVS 2009-06-10 09:22:30

2

您只可以通過設置CMD的使用塊之前爲null避免這種情況:

SqlCommand cmd=null; 

    using (new DisposableComposite(
     () => cmd = new SqlCommand(), 
     () => cmd.Connection)) // <- compiler error - variable not instantiated 
    { 
     // code 
    } 
+0

...但這不會導致cmd.Connection拋出一個NullReferenceException?那個Func委託會「查看」實例化的cmd變量嗎? – 2009-06-10 09:23:10

+0

它不會拋出異常,因爲第一個委託中的分配將首先發生。代理將看到變量,因爲「閉包」,但這是無法在簡短評論中解釋的:) – 2009-06-10 09:33:21

0

與馬克同意這並沒有真正適合我。

另一種選擇是定義一個新的Context類型對象,在Dispose上處理它提供的所有對象。

例如,

using (var ctx = GetContext()) { 
    var cmd = ctx.CreateCommand(); 
    cmd.Connection = ctx.CreateConnection(); 
} 
// cmd is Disposed 
// cmd.Connection is Disposed