2016-04-22 79 views
12

一個遺漏的二傳手財產和一個私人二傳手財產之間的區別是什麼?省略二傳手vs私人二傳手?

public string Foo { get; private set; } 

VS

public string Foo { get; } 
+5

簡單:一個遺漏setter **的屬性沒有setter **。您不能在屬性聲明或構造函數之外重新分配屬性。 – BoltClock

+3

這個問題怎麼來得到提升?我認爲這是微不足道的... – Alex

+3

重複提醒:http://stackoverflow.com/questions/3847832/understanding-private-setters,http://stackoverflow.com/questions/4948816/getters-setters-and-properties-最佳做法-java-vs -c-sharp – Tushar

回答

19

在C#6中,get;只有屬性只能從構造函數中設置。從其他地方,它是隻讀的。

一個private set;屬性可以從該類中的任何地方設置。

+0

我明白了。我想知道爲什麼功能存在遺漏setter。聲明一個只能由構造函數設置的屬性,或者通過類內部的方法聲明一個屬性的原因是什麼? – Fred

+0

爲防止在該方法內部錯誤地設置該屬性? –

7

從類外,如果使用此語法它不會改變任何東西:

public string Foo { get; } 

但你不能內更新Foo除了在構造函數中,類需要這樣做,您需要私有設置器:

public string Foo { get; private set; } 
+1

*你將無法在課堂內更新Foo *錯誤。你只能在構造函數中設置它。 –

+0

@PatrickHofman感謝您的評論,我以前不知道! –

+0

有趣的是,每個答案都有這個特定的部分錯了,仍然得到了投票,而我的指出,從一開始,並沒有得到任何投票... –

3

具有省略setter的屬性只能在類構造函數(包括類內部)中讀取。

具有私有setter的屬性只能從外部讀取(即使是子類),但在內部可寫。

3

private setter是 - 好 - 一個私人設置的方法,你只能在你的課堂內使用。

省略 setter使財產readonly。所以你只能在你的構造函數中設置這個屬性的值或者通過靜態初始化。

5

區別在於生成的代碼會在第二種情況下產生只讀字段,顯然該屬性不會有setter。

讓我們做一個真實的例子:

public class Test 
{ 
    public Test(string name) { Name = name; } 
    public string Name { get; private set; } 
} 

編譯;這是這樣的:

public class Test 
{ 
    private string <Name>k__BackingField; 
    public Test(string name) 
    { 
     <Name>k__BackingField = name; 
    } 
    public string Name 
    { 
     get { return <Name>k__BackingField; } 
     private set { <Name>k__BackingField = value; } 
    } 
} 

正如你所看到的編譯器自動將改寫你的代碼有用於支持字段屬性。字段名稱將是神祕的名字,這是合法的.NET而不是C#這意味着你可以永遠寫C#代碼,將這樣一個自動生成的成員發生衝突。

基本上,在C#自動屬性僅僅是一個支持字段屬性語法糖,被編譯的實際屬性仍然有支持字段,你只是沒有把它明確寫入。

正如你可以看到它還會自動改寫構造函數直接寫入到外地。請注意,這將在該類中寫入屬性的任何地方完成,因爲無論如何都不可能有任何自定義代碼。

現在讓我們從屬性中刪除setter和看看會發生什麼:

public class Test 
{ 
    private readonly string <Name>k__BackingField; 
    public Test(string name) 
    { 
     <Name>k__BackingField = name; 
    } 
    public string Name 
    { 
     get { return <Name>k__BackingField; } 
    } 
} 

注意,字段現在只讀,並再次,顯然制定者已經從財產了爲好。

所以實際上現在與真正只讀屬性創建簡單類型的最佳方式,不光是屬性本身不可寫,但支持字段也是隻讀意味着你現在更好的裝備,輕鬆地編寫不可變類型

+0

有趣的是,我想這也適用於靜態只讀屬性(即當它只聲明一個自動獲取) –

+0

是的,'靜態'在這方面並不重要 –

+0

我沒有試圖看看發生了什麼在這種情況下(無論是實例還是私有屬性都只有'get;')。因此,我不會手動聲明更多'readonly'字段; P(除非我不需要封裝它們,但是在沒有封裝的情況下訪問類字段仍然是一種錯誤的編碼習慣)。 –