2010-09-15 17 views
7

C#中是否有任何方法將屬性標記爲確定性?屬性決定論

我問的原因是我經常發現自己聲明瞭一個局部變量並讀入一個屬性,而不是多次訪問屬性。

是否有任何方法可以將屬性修飾爲確定性,以便編譯器可以優化對該屬性的多次訪問?我猜在這種情況下,班級需要是不可改變的,並且是這樣裝飾的。

這是甚至存在的東西還是我抓着吸管?

回答

7

如果屬性是簡單,像一個隱含的屬性:

​​

或從本地變量讀取:

public int X { get { return _x; } } 

則編譯器將優化代碼,以便有沒有區別多次訪問該屬性並將該屬性放入一個變量並訪問該屬性。

我通過比較訪問屬性十次並將屬性複製到一個變量並訪問十次來驗證這一點,並且根本沒有可測量的差異。

一般屬性應該是輕量級的,這樣您就不必期望每次訪問時都有大量的處理。如果該屬性的值成本高昂,則該類應在內部緩存該值,以便讀取該屬性只會首次執行代價高昂的操作(延遲加載模式)。

如果一個屬性花費很多時間,它不應該是一個屬性,而是一個getter方法。

+0

+1 - 只有一個問題 - 如果編譯器確實做了這種優化,那麼它將如何解釋非不可變對象上的對象的變化 - 無論它是否來自同一個線程?您是否有可能驗證該房產獲得的房產價格非常低,在這種情況下,我應該停止對此進行肛門分析? :) – 2010-09-15 09:12:44

+0

@Matt Whitfield:當代碼被優化時,簡單的屬性將被實現。讀取該屬性實際上不會調用屬性getter來返回值,而是直接獲取該值,就像訪問類中的公共變量一樣。在C#代碼中,您可以在OOP代碼中獲得所需的抽象和隔離,但在編譯代碼中,您可以獲得公共變量的速度。 :) – Guffa 2010-09-15 09:24:12

+0

謝謝 - 我打算接受這個,因爲你在那裏的評論有點讓我理解當我問這個問題時我正在尋找的理解。 – 2010-09-15 09:26:13

0

除非你的財產的支持字段是readonly,你將如何解決線程問題?

5

C#中沒有任何機制允許您引入const屬性getter,即不改變對象狀態的getter。

微軟文件只是建議not to introduce any side-effects在干將:

這是一個不好的編程風格使用get訪問來改變對象的狀態。例如,以下訪問器每次訪問數字字段時都會產生更改對象狀態的副作用。

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); 
    } 
} 
+0

DateTime.Now是一個不會改變狀態但改變值的屬性。許多其他屬性反映的狀態可以通過其他方式進行更改,而不僅僅是get setter。 – 2010-09-15 09:01:53

+0

@Albin Sunnanbo:'DateTime.Now'在這裏不是一個好的例子,因爲它是靜態的,它*返回一個新的值類型。沒有狀態或價值改變。問題在於OP希望有一種機制保證後續調用相同的屬性(至少在單線程環境中)會產生相同的結果。 – 2010-09-15 09:07:05

+0

+1,這肯定會得到一票,但我真正想知道的是,如果你遵循了這些建議,是否有辦法強制編譯器意識到多個屬性獲取將返回相同的值,因此如果您在同一個作用域中多次使用相同的屬性值,那麼先編譯它們就好像您先聲明瞭一個局部變量。 – 2010-09-15 09:08:27

2

我猜你正在尋找readonly,但我不知道性能如何比較的局部變量。它只適用於字段,而不適用於屬性。

除了readonly並不意味着決定論。

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

只是意味着fixedList對象不能被替換,但內容仍然可以改變。