2009-06-10 69 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