Mat*_*eld 7 c# deterministic properties
在C#中有什么方法可以将属性标记为确定性的吗?
我问的原因是我经常发现自己声明一个局部变量并将属性读入其中,而不是多次访问该属性.
有没有什么方法可以将属性装饰为确定性的,这样编译器就可以优化对该属性的多次访问?我猜测在这种情况下,类需要是不可变的,并且这样装饰.
这是甚至存在的东西还是我抓着稻草?
如果属性很简单,就像隐式属性一样:
public int X { get; set; }
Run Code Online (Sandbox Code Playgroud)
或从本地变量读取:
public int X { get { return _x; } }
Run Code Online (Sandbox Code Playgroud)
然后编译器将优化代码,以便多次访问属性和将属性放入变量并访问它之间没有区别.
我通过比较1次访问属性的1亿次迭代并将属性复制到变量并访问了10次来验证这一点,并且根本没有可测量的差异.
一般来说,属性应该是轻量级的,这样您每次访问它时都不必期望任何繁重的处理.如果属性的值很难获得,则类应该在内部缓存该值,以便只读取该属性会使第一次进行昂贵的操作(延迟加载模式).
如果每次获得一个属性成本高昂,它根本不应该是一个属性,而是一个getter方法.
C#中没有允许你引入const属性getter的机制,即不改变对象状态的getter.
Microsoft文档建议不要在getter中引入任何副作用:
使用get访问器更改对象的状态是一种糟糕的编程风格.例如,以下访问器产生每次访问数字字段时更改对象状态的副作用.
Run Code Online (Sandbox Code Playgroud)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);
}
}
Run Code Online (Sandbox Code Playgroud)