2012-05-14 21 views

回答

1

我不認爲有一個標準的方法來做到這一點,因爲在C#中沒有官方的不變性概念。我能想到的唯一的辦法就是看某些事情,說明概率較高:

1)類型的所有屬性都設有私人set

2)所有字段是const/readonly或私人

3)沒有與明顯/已知的副作用

4)亦沒有方法,作爲一個結構體通常是良好的指示(如果它是BCL類型或由某人與此準則)

就像ImmutabeAttribute會很好。有一些想法here(在評論中的某處),但我還沒有在「現實生活」中看到過。

+0

+1鏈接 – Tilak

0

第一個跡象是概述中屬性的文檔顯示「獲取鍵/值對中的鍵」。 第二個更明確的指示,將是房產本身的描述:

"This property is read/only."

+1

屬性爲「只讀」的事實表明它「可能」是不可變的,但絕不意味着它實際上是。所有「只讀」意味着在這種情況下,不能使用屬性設置器來更改屬性的值。例如,'List '有一個只讀屬性'Count',它不能通過存儲新的期望值來改變,但可以通過添加或刪除列表中的項目來改變。 – supercat

+0

OP的問題是:「我無法在文檔中的任何位置找到KeyValuePair的Value屬性無法更改的地方。它絕對是有記錄的。其實很清楚。它說:「你不能給KeyValuePair.Value賦值」。如果這不是應該如何閱讀文檔,我建議扔掉90%的文檔。雖然我正式同意你的意見(也就是說,按照你的例子,「Count」也是一個屬性,但不能直接改變,這是一個派生屬性),我仍然堅持我的觀點,即文檔是絕對完全清楚OP的問題。 –

0

我不認爲你可以通過看的文檔找到不可改變的「證據」,但也有幾個強勢指標:

  • 這是一個structwhy does this matter?
  • 它沒有可設置的公共屬性(均爲只讀)
  • 它沒有明顯的突變方法

對於確切的證據證明我建議下載BCL的reference source從微軟或使用IL反編譯器來告訴你一個類型會是什麼樣子的代碼。

+0

我同意結構部分,這是我第一眼看到的唯一線索。檢查可設置的公共屬性/明顯的增變方法是非常困難的。例如DateTime類提供了幾個靜態方法,它們使用修改後的數據創建新的DateTime。它需要非常仔細的觀察才能確定。 – Tilak

+1

我不同意結構部分。我看到大量的代碼不是從構造函數初始化struct字段/屬性,而是從使用struct的方法初始化。結構在其字段設置後未被修改的事實不會使其不可變。 – hvd

+0

或者,簡單地說,使結構不可變是件好事,但是結構究竟是否是可變的,就像類一樣,取決於它是否具有公共字段或增量方法(包括屬性設置器) – hvd

0

A KeyValuePair<T1,T2>是一個結構體,如果沒有Reflection,只能通過複製另一個包含所需值的KeyValuePair<T1,T2>的內容在其構造函數外突變。需要注意的是該語句:

 
    MyKeyValuePair = new KeyValuePair(1,2); 

像結構中的所有類似的構造函數調用,實際上是通過創建的KeyValuePair<int,int>一個新的臨時實例(本身執行構造函數之前發生),設置該實例的字段值(用做構造函數),將該新臨時實例的所有公共和私有字段複製到MyKeyValuePair,然後丟棄該臨時實例。

考慮下面的代碼:

 
static KeyValuePair MyKeyValuePair; // Field in some class 

// Thread1 
    MyKeyValuePair = new KeyValuePair(1,1); 
    // *** 
    MyKeyValuePair = new KeyValuePair(2,2); 

// Thread2 
    st = MyKeyValuePair.ToString(); 

因爲MyKeyValuePair恰恰是4個字節,在線程1第二個語句將同時更新這兩個字段。儘管如此,如果Thread1中的第二個語句在Thread2的評估MyKeyValuePair.Key.ToString()MyKeyValuePair.Value.ToString()之間執行,則第二個ToString()將對結構的新的突變值起作用,即使第一個已完成的ToString()對突變之前的值進行操作。

所有非平凡的結構體,無論它們是如何聲明的,它們的字段都具有相同的不變性規則:可以改變結構的代碼可以改變它的字段;無法更改結構的代碼不能更改其字段。有些結構可能會迫使人們去改變其中的一個領域,但將結構類型設計爲「不可變」既不必要也不足以確保實例的不可變性。 「不可變的」結構類型有一些合理的用途,但是如果有什麼需要更多的關注比公開域公開的結構所需的更多的用例。

相關問題