C# 中有什么方法可以将属性标记为确定性的吗?
我问的原因是我经常发现自己声明一个局部变量并将一个属性读入其中,而不是多次访问该属性。
有什么方法可以将属性装饰为确定性的,以便编译器可以优化对该属性的多次访问?我猜在这种情况下,该类需要是不可变的,并被这样装饰。
这是什至存在的东西还是我在抓着稻草?
C# 中有什么方法可以将属性标记为确定性的吗?
我问的原因是我经常发现自己声明一个局部变量并将一个属性读入其中,而不是多次访问该属性。
有什么方法可以将属性装饰为确定性的,以便编译器可以优化对该属性的多次访问?我猜在这种情况下,该类需要是不可变的,并被这样装饰。
这是什至存在的东西还是我在抓着稻草?
如果属性很简单,比如隐式属性:
public int X { get; set; }
或从局部变量中读取:
public int X { get { return _x; } }
然后编译器将优化代码,以便多次访问属性和将属性放入变量并访问它之间没有区别。
我通过比较访问属性十次并将属性复制到变量并访问十次的 1 亿次迭代来验证这一点,根本没有可测量的差异。
通常,属性应该是轻量级的,这样您就不必在每次访问它时都进行繁重的处理。如果该属性的值获取成本很高,则该类应在内部缓存该值,以便读取该属性只会在第一次进行昂贵的操作(延迟加载模式)。
如果每次获取一个属性的成本很高,那么它根本不应该是一个属性,而是一个 getter 方法。
C# 中没有允许您引入 const 属性 getter 的机制,即不改变对象状态的 getter。
Microsoft 文档只是建议不要在您的 getter中引入任何副作用:
使用 get 访问器更改对象的状态是一种糟糕的编程风格。例如,以下访问器会产生副作用,即每次访问 number 字段时都会更改对象的状态。
private int number; public int Number { get { return number++; // Don't do this } }
正如Daren 所提到的,要考虑的另一个方面是多线程(除非您的对象是真正不可变的)。如果另一个线程更改了对象状态以使 getter 在第二次调用时返回不同的值怎么办?编译器没有简单的方法来做出任何保证,例如在下面的场景中:
class List
{
IList data;
// called several times on thread A
// property has no side-effects
public int Count { get data.Length; }
// called several times on thread B
public void Add(object o)
{
data.Add(o);
}
}
我猜您正在寻找readonly
,但是我不确定性能与局部变量的比较。它仅适用于字段,不适用于属性。
此外readonly
并不意味着确定性。
private readonly List<string> fixedList = new List<string>();
只是表示fixedList对象不能被替换,但是内容还是可以改变的。
除非您的属性的支持字段是readonly
,否则您将如何解决线程问题?