2012-11-22 13 views
4

所以設計一個不可改變的類應該用它獲取屬性這樣在.net中創建不可變類型時,它是否有效具有公共字段?

public sealed class Person 
{ 
    readonly string name; 
    readonly int age; 

    public Person(string name, int age) 
    { 
     this.name = name; 
     this.age = age; 
    } 

    public string Name 
    { 
     get { return name; } 
    } 

    public int Age 
    { 
     get { return age; } 
    } 
} 

或者是有效的,當暴露公共只讀字段

public sealed class Person 
{ 
    public readonly string Name; 
    public readonly int Age; 

    public Person(string name, int age) 
    { 
     Name = name; 
     Age = age; 
    } 
} 
+0

可能重複的[在C#中不可變和只讀的含義是什麼?](http://stackoverflow.com/questions/6849114/what-does-immutable-and-readonly-mean-in-c) –

+4

@ssg:而不是重複;那另一個問題甚至沒有提到屬性。 –

回答

10

雖然這兩個選項會使你的對象,其字段不能從外部改變,同樣的準則適用於不可變對象另有:

使用屬性,而不是公開暴露你的領域仍然是一個優勢;你沒有檢查任何輸入值,但是,你的類型的未來版本可能會計算一些值,而不是直接從內部字段讀取它們。通過使用屬性,您可以隱藏該實現細節,從而增加您對未來更改的靈活性。

1

.net中public readonly類字段的一個主要問題是,從外部代碼的角度來看,readonly聲明所做的唯一一件事就是用readonly屬性標記字段(我忘記了拼寫和套管)。雖然有些語言會在外部代碼中承認這些屬性,但是一種語言如果選擇了這種屬性,它可以忽略這些屬性。如果具有public readonly字段的對象暴露於使用忽略只讀屬性的語言編寫的代碼中,則該代碼可以像寫入屬性不存在一樣容易地寫入這些字段。

結構是另一回事。如果存儲在現場foo一個結構有一個名爲boz一個它自己的領域,那麼代碼可以寫foo可以寫入foo.boz,哪些不能寫foo代碼不能寫入foo.boz無論boz是公共的還是私有的,或者它是否打算成爲可變或不可變的。這是因爲如果foo1是同一類型的結構,則語句foo = foo1不會使foo引用與foo1相同的實例,而是通過突出顯示foo中的所有公用和專用字段以匹配相應字段的值在foo1

盒裝值類型更糟;如果有一個Object持有任何值類型的盒裝實例,則該值可能會被另一個類型替換。甚至像Int32這樣的假定不可變類型,在裝箱時,表現爲可變引用類型。

因此,使用結構類型時,應該通過存儲在確切的結構類型的私有字段的結構執行不變性。試圖使struct字段不可變可以使該類型的實例更具有麻煩,但對結構實例的可變性或不可變性沒有實際影響。

+0

你確定「一種語言可以忽略這些屬性,如果它選擇」? – Simon

+0

@Simon:CLI肯定不會在乎 - 嘗試通過反射來改變'readonly'屬性的值,並且(例如,與將某些屬性分配給沒有定義setter的屬性相反),不會有任何異常;該屬性將被改變。 –

+0

這就在聲明依賴屬性的傳統方式上添加了一個有趣的角度,BTW。 –

相關問題