2011-02-09 58 views
81

我現在正在參加一個C#課程,我正試圖找出最好的方法。我來自Java背景,所以我只熟悉Java最佳實踐;我是C#新手!吸氣劑,固體劑和性質最佳實踐。 Java與C#

在Java中,如果我有私人財產,我這樣做;

private String name; 

public void setName(String name) { 
    this.name = name; 
} 

public String getName() { 
    return this.name; 
} 

在C#中,我發現有很多方法可以做到這一點。

我能做到像Java:

private string name; 

public void setName(string name) { 
    this.name = name; 
} 

public string getName() { 
    return this.name; 
} 

或者,我可以這樣來做:

private string name; 

public string Name { 
    get { return name; } 
    set { name = value; } 
} 

或者:

public string Name { get; set; } 

哪一個我應該使用,以及什麼每種方法都包含哪些警告或微妙之處?在創建類時,我遵循從Java中知道的一般最佳實踐(尤其是閱讀Effective Java)。例如,我贊成不變性(只在需要時才提供給定員)。我只是很好奇,看看這些實踐如何適應用C#提供setter和getter的各種方式;從本質上講,我如何將Java世界的最佳實踐轉化爲C#?

編輯

我張貼此爲喬恩斯基特的答案評論,但隨後得到了久:

怎麼樣一個不平凡的性質(即具有顯著處理和驗證也許)?我仍然可以通過公開財產揭露它,但邏輯封裝在getset?爲什麼會/應該通過專用的setter和getter方法(以及相關的處理和驗證邏輯)來做到這一點。

回答

79

前C#6

我用最後的這些,對於一個微不足道的財產。請注意,我會稱這是一個public屬性,因爲getter和setter都是公共的。

不變性對於自動實現的屬性有點痛苦 - 你不能寫一個只有吸氣劑的自動屬性;你能來最接近的是:

public string Foo { get; private set; } 

這是不是真的不可改變 ...只是一成不變的類的外部。所以,你可能希望使用真正只讀屬性,而不是:

private readonly string foo; 
public string Foo { get { return foo; } } 

你肯定不想寫getName()setName()。在一些情況下,編寫Get/Set方法而不是使用屬性是有意義的,特別是如果它們可能是昂貴的並且您希望強調這一點。然而,你會想遵循PascalCase的.NET命名約定來處理方法,並且你不希望這樣的普通屬性用普通的方法來實現 - 這裏的屬性更加地道。

C#6

萬歲,我們終於等來了合適的只讀自動實現的屬性:

// This can only be assigned to within the constructor 
public string Foo { get; } 

同樣爲只讀屬性,其需要做一些工作,你可以使用成員身份屬性:

public double Area => height * width; 
+5

更確切的:任何代碼reiew會指出,Java的方式是繞過有效的langauge和運行一個黑客(!)構造並終止屬性的使用作爲proeprty(即object.property =「value」)。在一些團隊中,這會引發一場關於態度的良好談話 - 取決於資歷和激勵,以便將這種態度用於競爭對手。嚴重的是,不要打仗LANGAUGE。特別是因爲java的「方式」是爲了不修改不動產支持的語言而選擇的黑客。 – TomTom 2011-02-09 18:24:10

+1

我想好消息是我的回答似乎與您提到的任何內容都不矛盾。壞消息是你的手指比我的快得多。偉大的洞察力,並感謝增加的細節。 – jeremyalan 2011-02-09 18:37:25

+4

要回答你的編輯:你可以使用get/set方法以及你想要的任意數量的邏輯。我們經常這樣做,特別是對於驗證。但是,最佳實踐並不是在屬性中包含很多緩慢的邏輯(例如數據庫訪問),危險邏輯(異常拋出)或突變(更改很多狀態)。預計財產或多或少會像一個簡單的狀態。更多的東西應該用一個函數來表示。 – CodexArcanum 2011-02-09 20:38:23

4

無論您在C#中選擇哪種方式,最終結果都是一樣的。你將得到一個帶有獨立getter和setter方法的backinng變量。通過使用屬性,您正在遵循最佳實踐,所以這是您想要得到多麼冗長的問題。

就我個人而言,我會選擇自動屬性,最後一個版本:public string Name { get; set; },因爲它們佔用最少的空間。如果您需要添加驗證等功能,您可以隨時擴展這些功能。

11

在C#中使用屬性,沒有獲取/設置方法。他們在那裏爲您提供方便,而且是慣用的。

至於你的兩個C#示例,其中一個就是另一個的語法糖。如果你需要的只是一個簡單的實例變量包裝,那麼使用auto屬性,當你需要在getter和/或setter中添加邏輯時,使用完整版本。

3

只要有可能,我寧願公開string Name { get; set; },因爲它簡潔易讀。然而,有時候這個是必要的

private string name; 

public string Name { 
    get { return name; } 
    set { name = value; } 
} 
4

在C#支持暴露私人領域獲取和/或設置的屬性。你提到的thie表單是一個autoproperty,get和set會爲你自動生成一個隱藏的pivot pivot字段。

我喜歡自動屬性,但是你不應該在C#中執行set/get方法對。

4
public string Name { get; set; } 

這簡直就是auto-implemented property,在技術上與普通屬性相同。編譯時會創建一個後臺字段。

所有屬性最終都轉換爲函數,所以最終的實際編譯實現與您在Java中使用的相同。

當您不必在後臺字段上執行特定操作時,使用自動實現的屬性。否則使用普通財產。當操作有副作用或計算成本高時使用get和set函數,否則使用屬性。

3

如前所述,所有這些方法都會產生相同的結果。最重要的是你選擇一個會議並堅持下去。我更喜歡使用最後兩個屬性的例子。

3

在C#中,首選方法是通過屬性而不是getX()setX()方法。此外,請注意,C#不要求屬性同時具有get和set - 您可以擁有隻讀屬性和只設置屬性。

public boolean MyProperty 
{ 
    get { return something; } 
} 

public boolean MyProperty 
{ 
    set { this.something = value; } 
} 
3

首先讓我試着解釋一下你寫的:

// private member -- not a property 
private string name; 

/// public method -- not a property 
public void setName(string name) { 
    this.name = name; 
} 

/// public method -- not a property 
public string getName() { 
    return this.name; 
} 

// yes it is property structure before .Net 3.0 
private string name; 
public string Name { 
    get { return name; } 
    set { name = value; } 
} 

這種結構也採用了時下但如果你想要做一些額外的功能,例如當一個價值在於它是最合適的設置你可以解析大寫它,並將其保存在私人成員內部以供更改內部使用。

使用.NET框架3.0

// this style is introduced, which is more common, and suppose to be best 
public string Name { get; set; } 

//You can more customize it 
public string Name 
{ 
    get; 
    private set; // means value could be set internally, and accessed through out 
} 

祝你更好的運氣,在C#

16

如果你需要的是存儲一些數據的變量:

public string Name { get; set; } 

想使它看起來只讀?

public string Name { get; private set; } 

甚至更​​好...

private readonly string _name; 

... 

public string Name { get { return _name; } } 

想要做一些價值分配屬性之前檢查?

public string Name 
{ 
    get { return m_name; } 
    set 
    { 
     if (value == null) 
     throw new ArgumentNullException("value"); 

     m_name = value; 
    } 
} 

一般來說,GetXyz()和SetXyz()在某些情況下只使用,你只需要使用你的時候感覺對上消化道。一般來說,我會說我期望大多數get/set屬性不包含很多邏輯,並且只有很少的(如果有的話)意想不到的副作用。如果讀取屬性值需要調用服務或從用戶獲取輸入以構建我請求的對象,那麼我會將其包裝到一個方法中,並將其稱爲BuildXyz()而不是GetXyz()

2

像這裏的大多數答案一樣,使用自動屬性。直觀,少量的代碼,它更乾淨。如果您應該序列化您的課程,請標記課程[Serializable]/[DataConract]屬性。如果你正在使用[DataContract]馬克成員與

[DataMember(Name="aMoreFriendlyName")] 
public string Name { get; set; } 

私人或公共setter方法取決於您的喜好。

另請注意,自動屬性需要獲取者和設置者(公有或私有)。

/*this is invalid*/ 
public string Name 
{ 
    get; 
    /* setter omitted to prove the point*/ 
} 

或者,如果你只是想獲得/集,創建一個支持字段自己