2012-01-10 134 views
3

在C#中,我們可以創建一個自動實現的屬性一樣,使用自動實現的屬性或由我們自己實現屬性

public string MyValue{get;set;} 

然而,我們也可以通過我們自己一樣,

private string _myValue; 
public string MyValue 
{ 
    get { retrun _myValue; } 
    set { _myValue = value; } 
} 

創建屬性我的問題是我們應該在哪種情況下使用汽車,以及我們應該實施哪種情況?

+1

我可以認爲擁有第二種風格的一個原因是,當你想首先初始化_myValue並在ctor中使用默認值時。其他方面,我沒有找到有這種風格的其他原因。 – Zenwalker 2012-01-10 02:20:21

+0

StackOverflow不是討論這些事情的地方。網上有很多資源,你可以從中得到答案。例如:http://msdn.microsoft.com/en-us/library/bb384054.aspx – evasilchenko 2012-01-10 02:20:25

+0

任何時候您需要直接控制存儲的值(想法驗證),或者需要從內部私下訪問該值你的類本身(即使考慮在get或set方法中使用不同的訪問修飾符),你需要自己實現這個屬性。否則,我傾向於使用自動屬性功能來保存幾行代碼。 – 2012-01-10 02:23:21

回答

5

至少有一個明確的情況,您不應該使用自動實現的屬性:兩個不同DLL之間的任何類型的二進制序列化。

二進制序列化依賴於私有成員,並且自動實現的屬性的私有支持成員不能保證在每個已編譯的DLL中相同,因此二進制序列化可能會非常糟糕。

不使用自動實現的屬性的另一個原因是,您將失去控制權,是指定支持字段爲NonSerialized的能力,但在此情況下,爲屬性創建支持字段已足夠簡單。

如果您或您使用的任何產品在成員(即WCF)上執行了反射,則會看到損壞的支持字段名稱,而不是您創建的「漂亮」支持字段。

如果您之前提供了對服務的訪問權限,或者如果您在接收端反序列化爲相同的類結構(即在WCF管道的兩端使用相同的類),這可能非常重要。在這種情況下,您不一定能夠反序列化,因爲您可以保證支持字段名稱是相同的,除非您共享相同的DLL而不是源代碼。

例如,假設您有一項服務通過WCF將您的一些業務對象公開給您已創建的Silverlight客戶端。爲了重用您的業務邏輯,您的Silverlight客戶端會添加對業務對象源代碼的引用。如果您有自動實現的屬性,則無法控制後備字段名稱。由於WCF序列化成員而不是屬性,因此無法確定從WCF服務傳輸到Silverlight的對象是否會正確反序列化,因爲支持字段名稱幾乎肯定會不匹配。

3

在你給出的例子中,中間語言(IL)大致相同。

然而,當你需要編碼干預邏輯而不影響使用它的客戶端時,可能會有時間。自動屬性對於這種情況非常有用,因爲它可以被聲明,然後被改爲添加一個明確的後臺字段。可以在getter/setter中操作後臺字段以滿足驗證和驗證要求,而不會影響庫或程序集的其他位。最終效果是,您可以在不改變更改的情況下使財產「安全」。

另一個原因宣佈支持字段時,例如,在WPF其中一個屬性聲明...

private string myVar; 
public string MyProperty 
{ 
    [DebuggerStepThrough] 
    get { return myVar; } 
    [DebuggerStepThrough] 
    set 
    { 
     if (value != myVar) 
     { 
      myVar = value; 
      OnPropertyChanged("MyProperty"); 
     } 
    } 
} 

在此聲明,一旦支持字段已被分配,二傳手然後調用的事件處理程序讓外部偵聽器知道該屬性的值已更改。

因此,作爲一般規則,您最初可以使用自動語法聲明屬性,以便在需要干預時使用getters/setter對它們進行充實。

4

我對這個問題採取的方法很簡單但很實用。

始終使用AutoImplemented屬性,直到顯而易見您需要做一些不同的事情,此時我重構。並且它變得明顯。

我喜歡自動屬性的可讀性,但他們確實有其侷限性。使用ReSharper這樣的工具使得重構變得非常簡單,在某些情況下,R#甚至會爲您做出決定。