表达式捕获闭包,当它应该引用类实例时

本文关键字:引用 实例 闭包 表达式 | 更新日期: 2023-09-27 18:12:17

我有一种情况,代码在两个不同的开发盒上编译时表现不同。我不知道为什么。我不知道什么关键词能最好地描述这个问题。

当Rabbit在一个box源上被调用时,它的值为

{() => Program.Names}

在另一个方框源的值为

{() => value(NPC.Program+<>c__DisplayClass1_0).Names}

无论在什么计算机上编译,Hole都具有该值。

{() => value(NPC.Program+<>c__DisplayClass1_0).closure}

我想弄清楚为什么一台机器有类的表达式,而另一台机器在调用Rabbit时有闭包的值。我还想知道有没有办法控制它。谢谢!

class Program
{
    public static ObservableCollection<string> Names = new ObservableCollection<string>();
    static void Main(string[] args)
    {
        string closure = "closure";
        if(closure.Length > 0)
        {
            GoingDown(p => {
                closure.ToString();
                Names = new ObservableCollection<string>();
                Rabbit(() => Names);
                Hole(() => closure);
            }, closure);
        }
    }
    public static void Rabbit<SourceType>(Expression<Func<ObservableCollection<SourceType>>> source)
    {
        "Testing".ToString();
    }
    public static void Hole(Expression<Func<object>> source)
    {
        "Testing".ToString();
    }
    public static void GoingDown(Action<object> a, object target)
    {
        Action b = () =>
        {
            a(target);
        };
        b();
    }
}

表达式捕获闭包,当它应该引用类实例时

首先:正如注释所指出的,了解。net/c#/etc的哪些版本产生了哪些行为是有帮助的。

第二个问题:如果是正确的,那么哪个行为是正确的?说明书上没有说。它为编译器提供了广泛的自由度,可以根据需要将lambdas实现为委托和表达式树。

第三:哪个更好?显然,没有必要将静态字段名复制到闭包类中。我希望生成非闭包版本;我怀疑生成闭包的版本有bug。也许这个错误在不显示闭包语义的版本中已经被修复了。

第四:你能控制这种行为吗?显然是的,你有一台有不良行为的机器和一台没有,所以你可以简单地选择将有不良行为的机器沉入海底,而使用有理想行为的机器。

或者:没有要求你使用编译器的lambda语义实现。lambda是一种语法糖;如果你不喜欢编译器给你的表达式树,你可以自由地"手工"生成表达式树。