捕获的变量实例化问题

Posted

技术标签:

【中文标题】捕获的变量实例化问题【英文标题】:Captured variable instantiating problem 【发布时间】:2009-06-10 09:10:37 【问题描述】:

我目前正在思考一些我无法理解的想法。

问题是我想使用一个 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();
        
    

【问题讨论】:

【参考方案1】:

你的意思是添加:

SqlCommand cmd = null;

(解决了“确定赋值”的问题;它明确赋值的......一个空值;-p 然后我们在使用它之前更新这个值)。

不过,IMO,您最好使用嵌套的 using 语句……而且(从代码中)不清楚实际连接的来源……

using(var conn = new SqlConnection(...))
using(var cmd = conn.CreateCommand()) 
    // ...

【讨论】:

该死的..这很容易。我想我需要再来一杯咖啡。 :)【参考方案2】:

您只能通过在 using 块之前将 cmd 设置为 null 来避免这种情况:

    SqlCommand cmd=null;

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

【讨论】:

...但这不会导致 cmd.Connection 抛出 NullReferenceException 吗?该 Func 委托会“看到”实例化的 cmd 变量吗? 它不会抛出异常,因为第一个委托中的分配将首先发生。由于“闭包”,代表将看到该变量,但这是无法在简短评论中解释的内容:) @Fredrik:这是捕获的外部变量的定义:en.csharp-online.net/… 是的,我评论的背景是我运行了一个类似的测试,但它使用的是字符串。这是一个糟糕的选择,因为它们是不可变的,这会导致完全不同的结果。谢谢你让我重新振作起来:)【参考方案3】:

同意 Marc 的观点,这感觉不太对。

另一个选项是定义一个新的 Context 类型对象,它在 Dispose 上处理它提供的所有对象。

例如。

using (var ctx = GetContext()) 
   var cmd = ctx.CreateCommand();
   cmd.Connection = ctx.CreateConnection();

// cmd is Disposed 
// cmd.Connection is Disposed 

【讨论】:

是的.. 这段代码的灵感来自另一个问题 (***.com/questions/966086/…),我只是在玩耍并寻找更好的方法。我并不是说这实际上是一种更好的方法。

以上是关于捕获的变量实例化问题的主要内容,如果未能解决你的问题,请参考以下文章

为实例化的表单对象捕获 onClose 事件

Javascript 不会在 WebSocket 实例化中捕获错误

AngularJS:未捕获的错误:[$injector:modulerr] 无法实例化模块?

未捕获的错误:[$injector:modulerr] 添加 $cordovaGeolocation 和 $ionicPopup 时无法实例化模块

我为一个类声明了一个变量,并将其传递给一个方法来实例化它,但原始变量仍未实例化

coq 中存在变量的实例化规则