【问题标题】:Closure and property关闭和财产
【发布时间】:2012-10-08 02:13:21
【问题描述】:
var a = "test";
var @delegate = () => a;

Assert.AreEqual(@delegate(),"test"); //true

a = "12345678"

Assert.AreEqual(@delegate(),"test"); //still true, due to closure.

但是,如果变量 a 是类级别的属性,那么第二个断言会返回什么 - 真还是假?

例如,如果 a 是

string _a;
string a {get {return _a;} set{_a = value;}}

如果 a 是方法而不是属性,我知道第二个断言将是错误的。

【问题讨论】:

  • 那么问题是什么?
  • 问题是,这对财产有什么不同吗?我知道如果我用函数调用 'a()' 替换 'a' 我不会得到缓存效果。它与属性的工作方式相同吗?
  • @Alwyn 是的,看看我的回答 - 属性获取是一个方法调用。
  • 只是好奇,你为什么不自己尝试一下?

标签: c# .net lambda closures


【解决方案1】:

闭包捕获变量,而不是值。第二个断言是错误的。

另外,值得注意的是属性方法。一对 get set 访问器,用于此类属性

private string _a;

public string a
{
    get { return _a; }
    set { _a = value; }
}

实际上产生了这样的代码

private string _a;

public string get_a()
{
    return _a;
}

public void set_a(string value)
{
    _a = value;
}

变量等属性的使用只是语法糖

【讨论】:

  • 我认为它会复制内存位置 - 除了本机类型。带有新分配的 a 现在指向与委托内部的 a 不同的内存位置。是的,我知道属性只是语法糖,但表达式编译器是否复制指向值或函数的指针?
  • 对不起,我不太明白。委托的创建上下文被保留,因此它知道从哪个实例(或更一般的范围)读取哪个变量以获得它需要的值 - 这不是你的意思吗?
  • 我不这么认为,由于某种原因,该值正在缓存。即使原始值发生了变化,表达式中的值也没有变化。我知道这与字段有关,我想知道属性的行为是否有任何不同。
  • 如果您发布您的实际代码,它可能有助于解决这个问题。
【解决方案2】:

它们的行为完全相同。

public void ClosureOverVariable()
{
    var a = "x";

    Func<string> d = () => a;

    Console.WriteLine(d()); // print "x"

    a = "y";

    Console.WriteLine(d()); // print "y"
}

class Foo
{
    public string X { get; set; }
}

public void ClosureOverProperty()
{
    var a = new Foo
        {
            X = "a"
        };

    Func<string> d = () => a.X;

    Console.WriteLine(d()); // prints "a"

    a.X = "y";

    Console.WriteLine(d()); // print "y"
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多