C# - 每次访问属性时都会重新计算属性吗?

时间:2011-04-18 15:33:28

标签: c# properties

假设以下简单代码:

private const int A = 2;
private const int B = 3;


public int Result
    {
        get
        {
            return A * B;
        }
    }

我多次使用Result属性 每次都会重新计算产品A * B吗?

8 个答案:

答案 0 :(得分:5)

如果您没有将值存储在私有字段中,那么是的,它会在每次访问时重新计算。

缓存结果的方法是

private int? _result;
public int Result {
  get {
     if (!_result.HasValue) {
       _result = A*B;
     }
     return _result.Value;
  }
}

这里有几点需要注意。

首先,如果你的所有操作都是针对常量的,那么编译器会自动为你优化这些操作。这意味着乘法操作实际上不会在运行时执行。这意味着你不应该担心它。

第二,如果操作仅限于对两个现有变量执行简单的算术运算,那么每次计算它将比上面的“if”测试更快。此外,在这种情况下,带有私有字段的本地存储会增加内存占用,这是没有用的原因。

第三个​​,如果底层变量在对属性getter的调用之间更改(即A或B有一个新值),那么 NOT < / strong>重新计算这些新值。

这给我们留下了实际使用上述代码的几个原因之一:操作需要很长时间,并且它操作的数据在对属性的调用之间没有变化。我现在可以想到的另一个原因是,如果属性是一个必须在调用之前被实例化的对象。

答案 1 :(得分:3)

属性并不神奇。它们只是两种方法的语法糖,get_Xxxset_Xxx。知道了,很明显每次访问属性时,get部分内的所有代码都会被执行。

答案 2 :(得分:2)

由于值为const,编译器可能会优化这种情况。

但如果它们不是const,则每次都会计算出来。

答案 3 :(得分:1)

是。但是,一个好的经验法则是,如果你想要这样的操作,它应该是一种方法。

答案 4 :(得分:1)

是的,属性只是每次访问时执行的特殊方法。如果要缓存结果,请将其存储在成员变量中,也许是可以为空的int,并在返回之前检查它是否已经计算(也称为延迟初始化):

int? _result = null;
public int Result {
    get {
        if ( _result == null )
            _result = A * B;
        return _result;
    }
}

答案 5 :(得分:1)

在反射器中打开装配,编译器将优化乘法,因为它们是const int

public class FooContainer
{
    private const int A = 2;
    private const int B = 3;


    public int Result
    {
        get
        {
            return A * B;
        }
    }
}

将成为:

public class FooContainer
{
    // Fields
    private const int A = 2;
    private const int B = 3;

    // Properties
    public int Result
    {
        get
        {
            return 6;
        }
    }
}

但是,如果您将变量更改为int并且不存储计算,则每次都会进行评估。

示例:

public class FooContainer
{
    private int A = 2;
    private const int B = 3;


    public int Result
    {
        get
        {
            return A * B;
        }
    }
}

变为:

public class FooContainer
{
    // Fields
    private int A = 2;
    private const int B = 3;

    // Properties
    public int Result
    {
        get
        {
            return (this.A * 3);
        }
    }
}

答案 6 :(得分:1)

大多数语言都没有定义优化的工作方式。通常的语言 - 律师短语“好像”,在这种情况下,C#定义很可能会说“每次调用时属性的值都返回,好像它被评估”。这使得编译器类型可以自由地执行任何保留记录行为的操作。

因此,编译器可能会优化它。通常,具有悠久历史和强调性能的编译器(C#具有悠久的历史和大量资源,而不是如此强调性能)试图弄清楚在什么情况下可以重用先前计算的结果。你的A和B被声明为CONSTS的事实表明编译器可以发现产品是一个常量,实际上它可以用const替换getter上的每个调用。

可以。它是否是一个悬而未决的问题。我怀疑微软会以“是的绝对做到这一点”来回答这个问题。

答案 7 :(得分:0)

每次调用属性时都会对其进行评估。如果你想要更高效的东西,你必须自己处理它。