2010-01-27 35 views
2

我主要來自Java世界。所以,C#屬性看起來不錯。爲什麼我需要一個通過公共財產公開的私人領域?

我知道用C#3.0或更高版本,我可以使用自動屬性。我更喜歡它:)。

我的問題是關於一個(也許更老)代碼,我可以看到這一點:

private int age; 

    public int Age { 

    get { return age; } 
    set { age = value; }  
    } 

爲什麼我需要私人領域的時代?我真的藏在這裏了嗎?

編輯:

我完全理解的getter和setter的需要。我提到我來自Java世界,並一直這樣做。

我明白在C#3.0或以上的自動屬性是syntally糖。但也許我的問題有一個更簡單的答案。這是否意味着(低於C#3.0)該屬性不具有任何價值。所以它必須從其他領域獲得價值?

+4

這麼多可能的重複。這裏是開始http://stackoverflow.com/questions/295104/what-is-the-difference-between-a-field-and-a-property-in-c,當然,Jon Skeet的文章:http: //csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx – 2010-01-27 21:47:16

+0

由於@Jay和@womp在他們的答案中指出,你不需要*那個明確的私人領域。事實上,如果您的示例代碼是您的實際代碼,則可以使用自動屬性簡寫。如果您需要get/set中的其他邏輯,通常只會提供顯式屬性實現。 – JMD 2010-01-27 21:48:37

+0

我正在搜索,沒有找到我的答案(它在這裏...)。搜索谷歌,只有有用的信息是關於公共領域與公共財產的使用。我設置搜索引擎不喜歡我:)。拼寫檢查器在這裏不喜歡我。一切都是紅色的......只是不是我的一天。 – 2010-01-27 22:02:21

回答

3

舊版本的C#沒有自動屬性,所以您必須聲明屬性在您的示例中所採取行動的變量。現在,相同的代碼可以表示爲:

public int Age { get; set; } 

我認爲這可以回答你的問題。但是,如果您問「爲什麼不公開int age,並讓程序員直接在字段上設置值?」,則:

要記住的第一件事是將屬性訪問器編譯爲方法。這意味着,它有不同的ABI從剛讀/寫一個類的成員變量,即使它可能在語法上看起來是一樣的,如果你有:

class Fu { 
    public int Age; 
} 

那麼,這是什麼意思是,如果在某點下去,您需要添加一些Age字段已更改的通知 - 如果您正在使用屬性,則可以輕鬆地將此通知邏輯添加到屬性設置器,而不會破壞ABI。

public int Age { 
    get { return age; } 
    set { age = value; NotifySomeOtherCode(); } 
} 

如果你開始與公共領域,後來將其更改爲一個屬性將改變ABI這是壞的任何程序(一個或多個)可能取決於你的裝配。所以最好從屬性開始。

希望我做的意義......

+0

第一段是答案,但總是很高興有更多的東西 – 2010-01-27 22:25:37

1

在這種情況下,你不需要它。然而,如果你需要在setter或getter中做其他任何事情,那麼自動屬性將不起作用 - 你需要專用字段來操作。

1

C#中的自動屬性在編譯時最終在功能上與上面的代碼完全相同。編譯器爲您生成一個後臺字段。

所以你做需要支持一個屬性 - 一個字段或一些代碼 - 它只是用自動屬性的快捷方式照顧你。

+0

「正好」不是真實的,專用字段的實際名稱可能會有所不同。 – Lucero 2010-01-27 21:47:37

+2

我的意思是它功能上編譯爲相同的東西,而不是令牌相同。 – womp 2010-01-27 21:50:00

+0

我的問題是:什麼是私人領域的原因?好吧,我可以改變私人領域的名稱(它可以是任何其他領域)。我的公共財產仍然是相同的,這是我將在我的課堂上使用或計算財產中的其他私人領域。 – 2010-01-27 22:08:06

1

沼氣標準答案將是「封裝實施細節如何以及在何處存儲年齡」。

爲了檢索的目的,一個更現實的例子可能是有一天,您可能想以某種方式訪問​​該值,這意味着直接訪問不太好。例如,如果這是您可能在其他地方緩存的值,或者它是計算值。

就封裝設置過程而言,這意味着您可以將一些模型級驗證嵌入到setter中;如果有人試圖設置一個概念上無效的值,您可以拋出IllegalArgumentException並拒絕它。

在這些情況下,封裝意味着您的所有現有代碼都不必更改,因爲您必須將某個值包含在內。

2

舊版本的C#編譯器不支持自動屬性。

上面的代碼是這或多或少當量(假設該字段實際上從未直接使用):

public int Age { 
    get; 
    set; 
} 
0

屬性只是寫一對的一個很好的方式得到方法方法。在Java中,您可以這樣做:

private int age; 

public int getAge() { return age; } 
public void setAge(int value) { age = value; } 

您需要專用字段來存儲某個地方的年齡 - getAge和setAge只是方法。

這同樣適用於C#至版本3.0之前:

private int age; 

public int Age 
{ 
    get { return age; } 
    set { age = value; } 
} 

這是一個get和set方法,只是很好的配對,所以你可以寫x.Age = 21而不是x.setAge(21)

具有自動性,在C#編譯器生成的私有字段爲您(但它仍然存在!):

public int Age 
{ 
    get; 
    set; 
} 

自動屬性的好處是,你不必創建您可以自己手動備份字段。

手動版的好處是,你可以添加額外的邏輯來get和set方法,例如,參數驗證:

private int age; 

public int Age 
{ 
    get { return age; } 
    set { if (value < 0) throw new ArgumentException(); age = value; } 
} 
+0

我認爲這個問題更多的是它的好處嗎? – Rob 2010-01-27 21:47:22

0

隨着自動屬性,你需要去做這個。它沒有什麼問題,但有了自動屬性,您仍然可以使用財產簽名,這是重要的。在自動屬性之前,您必須爲您的財產設置後臺字段。只要您具有自動屬性,稍後可以使用明確的後臺字段將其更改爲格式,並且簽名保持不變。

但是,它沒有什麼問題。除了該公約正在變得更多地稱爲私人支持字段「_age」。

(我假設你知道爲什麼你想有一個財產,是否自動與否,而不是公共,原因是該對象有不同的簽名,如果你改變形成的公共領域的公共屬性,所以最簡單的方法就是從屬性開始,即使沒有額外的邏輯。)

0

也許你想在稍後的時間點改變setter或getter的行爲。例如記錄該值是從外部改變的。這不會與公共領域可能沒有屬性

private int age; 

    public int Age { 

    get { return age; } 
    set { 
     age = value; 
     Log("value of age changed"); 
    }  
    } 

隨着公共領域age,你必須在你改變年齡的值的代碼隨處記錄此。

0

在這種情況下,您不會隱藏任何內容,但它可以讓您自由地在以後向您的私人領域添加獲取/設置邏輯。所以任何使用該物業的人都不會注意到未來的區別。

0

在簡單的情況下沒有。但是,如果這兩種方法中的任何一種的實現需要額外的代碼,則可以更容易地維護與類的接口。

舉例來說,如果你需要添加一個改變事件給setter。

public int Age { 

    get { return age; } 
    set { 
      if (age != value) { 
       age = value; 
       OnAgeChanged(); 
      } 
     }  
    } 

你可以用屬性來做到這一點,而不是破壞客戶端代碼。一個領域沒有這個優勢。

0

getter和setter是公共接口,其他類交互。在複雜的系統中,通常最終會在getter和setter中進行驗證和其他工作。

專用字段供內部使用。如果您需要更改班級中的值,但繞過所有額外的工作,您將更改私有變量。

相關問題