假设以下简单代码:
private const int A = 2;
private const int B = 3;
public int Result
{
get
{
return A * B;
}
}
我多次使用Result属性 每次都会重新计算产品A * B吗?
答案 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_Xxx
和set_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)
每次调用属性时都会对其进行评估。如果你想要更高效的东西,你必须自己处理它。