C# 财产决定论

C# 财产决定论,c#,properties,deterministic,C#,Properties,Deterministic,在C#中是否有任何方法将属性标记为确定性 我问这个问题的原因是我经常发现自己声明了一个局部变量并将一个属性读入其中,而不是多次访问该属性 是否有任何方法可以将属性修饰为确定性的,这样编译器就可以优化对该属性的多次访问?我猜想在这样的场景中,类需要是不可变的,并进行这样的修饰 这是真的吗?还是我在抓救命稻草?除非你的属性的支持字段是只读的,否则你将如何解释线程问题?在C中没有机制允许你引入常量属性getter,即不改变对象状态的getter Microsoft文档仅在Getter中推荐: 使用ge

在C#中是否有任何方法将属性标记为确定性

我问这个问题的原因是我经常发现自己声明了一个局部变量并将一个属性读入其中,而不是多次访问该属性

是否有任何方法可以将属性修饰为确定性的,这样编译器就可以优化对该属性的多次访问?我猜想在这样的场景中,类需要是不可变的,并进行这样的修饰


这是真的吗?还是我在抓救命稻草?

除非你的属性的支持字段是只读的,否则你将如何解释线程问题?

在C中没有机制允许你引入常量属性getter,即不改变对象状态的getter

Microsoft文档仅在Getter中推荐:

使用get访问器更改对象的状态是一种糟糕的编程风格。例如,以下访问器会产生副作用,即每次访问number字段时都会更改对象的状态

private int number;
public int Number
{
    get
    {
        return number++;   // Don't do this
    }
}
正如达伦所提到的,另一个需要考虑的方面是多线程(除非你的对象真的是不可变的)。如果另一个线程更改了对象状态,因此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);
    }
}

我想您正在寻找,但是我不确定性能如何与局部变量进行比较。它只适用于字段,不适用于属性

此外,
只读
并不意味着决定论

private readonly List<string> fixedList = new List<string>();
private readonly List fixedList=new List();

只是意味着不能替换fixedList对象,但内容仍然可以更改。

如果属性很简单,例如隐式属性:

public int X { get; set; }
或从局部变量读取:

public int X { get { return _x; } }
然后,编译器将优化代码,以便多次访问属性与将属性放入变量并访问该变量之间没有区别

我通过比较访问一个属性十次的1亿次迭代和将该属性复制到一个变量并访问该属性十次来验证这一点,没有任何可测量的差异

一般来说,属性应该是轻量级的,这样您就不必期望每次访问它时都有任何繁重的处理。如果属性值的获取代价很高,则类应该在内部缓存该值,以便读取该属性只会在第一次执行代价很高的操作(延迟加载模式)


如果每次获取一个属性的成本很高,那么它不应该是一个属性,而应该是一个getter方法。

DateTime.Now是一个不会更改状态,但会更改值的属性。许多其他属性反映的状态可以通过除get setter之外的其他方法进行更改。@Albin Sunnanbo:
DateTime。现在
不是一个好例子,因为它是静态的,并且返回一个新的值类型。状态和值都没有改变。问题是OP希望有一种机制来保证对同一属性的后续调用(至少在单线程环境中)产生相同的结果。+1,这肯定会得到投票,但我真正想知道的是,如果您遵循了建议,有没有办法强迫编译器认识到多个属性GET将返回相同的值,因此,如果在同一范围内多次使用相同的属性值,则可以像首先声明局部变量一样编译它们。+1-只有一个问题-如果编译器仍然执行此优化,那么,它将如何解释对非不变对象上的对象所做的更改——无论这些更改是否来自同一线程?有没有可能您只是验证了一个简单的属性花费非常少,在这种情况下,我应该停止对此进行分析?:)@马特·惠特菲尔德:当代码被优化时,简单的属性将被拘留。读取属性实际上不会调用属性getter来返回值,而是直接获取值,就像访问类中的公共变量一样。在C#代码中,您可以获得OOP代码中所需的抽象和隔离,但在编译代码中,您可以获得公共变量的速度。:)谢谢-我会接受你的评论,因为你的评论给了我当我问这个问题时想要的理解。