2010-06-18 206 views
30

首先,我已閱讀了關於此主題的帖子列表,並且我並不認爲我已經掌握了屬性,因爲我已經瞭解了封裝和字段修飾符(私有,公共...等)。屬性與字段:需要幫助掌握屬性在字段上的用法

我已經學習了C#的一個主要方面,就是使用封裝在代碼中保護數據的重要性。我'認爲'我明白這是因爲使用修飾語(私人,公共,內部,受保護)的能力。然而,在瞭解了屬性之後,我不僅在理解屬性的使用方面存在困難,而且在理解C#中數據保護的整體重要性/能力(我認爲是封裝)。

更具體地講,一切我已閱讀,當我在C#中得到了性質是,你應該嘗試使用他們在的地方字段時,你可以因爲:

1)它們允許你如果直接直接訪問字段時無法更改數據類型。

2)他們的保護級別添加到數據訪問

然而,從我「想」我是來了解採用現場改性劑做了#2,這在我看來,性質只是生成額外的代碼,除非你有理由改變類型(#1) - 因爲你(或多或少)創建隱藏的方法來訪問字段,而不是直接。

然後就是可以將所有修飾符添加到屬性中,這進一步使我對需要屬性訪問數據的理解變得複雜。

我已經閱讀了許多關於「屬性」的不同作者的章節,沒有一篇真正解釋了對屬性與字段與封裝(以及良好的編程方法)的良好理解。

有人能解釋一下:

1)我爲什麼要使用屬性,而不是領域(尤其是當它出現,我只是添加額外的代碼

2)上的任何提示在追蹤其他人的代碼時,認識到使用屬性並且不把它們視爲簡單的方法(除get; set是顯而易見的)?

3)任何一般的經驗法則,當涉及到什麼時候使用什麼好的編程方法?

感謝和抱歉的長篇文章 - 我不想問一個已經被問到100x的問題,而沒有解釋我爲什麼再次提問。

+1

重複? http://stackoverflow.com/questions/2911945/method-calling-public-private-members-or-methods-best-practice-c-net/ – 2010-06-18 13:24:07

+2

似乎沒有人鏈接到[爲什麼屬性](http:///csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx)。在過去,我發現這個概述很有幫助。 – R0MANARMY 2010-06-18 14:19:04

回答

8

您不必擔心通過屬性訪問字段所需的額外代碼,它將由JIT編譯器(通過內聯代碼)「優化」掉。除非內聯過大,否則你需要額外的代碼。

以及用於定義簡單屬性的額外的代碼也微乎其微:

public int MyProp { get; set; } // use auto generated field. 

當你需要定製可以送花兒給人後來定義自己的領域。

所以,你剩下了額外的封裝/數據保護層,這是一件好事。

我的規則:總是暴露領域通過屬性

0

屬性是覆蓋領域執行封裝的首選方法。然而,它們的功能在於你可以公開一個不同類型的屬性並編組投射;你可以改變訪問修飾符;它們用於WinForms數據綁定;它們允許您嵌入輕量級的每個屬性邏輯,例如更改通知;等等。

在查看其他人的代碼時,屬性對方法具有不同的智能圖標。

如果你覺得性只是額外的代碼,我將與他們無論如何據理力爭,但堅持讓您的生活通過自動生成來自外地的財產更容易(右擊 - >重構 - >封裝字段...)

3

有些情況下使用一個簡單的現場不會造成損害,
一個屬性可以更容易地後來改變,也就是說,如果你想添加一個事件每當值改變或需要執行一些價值許多場景/範圍檢查。

另外,如果您有多個項目相互依賴,則必須重新編譯所有依賴字段更改爲屬性的項目。

2

why I would want to use properties instead of fields (especially when it appears I am just adding additional code

您想使用性能在田野監守,當您使用屬性,你可以在一個情況下使用的事件和他們在一起,所以當你想要做一些動作時,屬性發生變化時,可以將一些處理器到PropertyChanging或PropertyChanged事件。如果是田地,這是不可能的。字段可以是公開的,也可以是私人的,也可以是受保護的,如果是道具,您可以公開只讀,但可以私下寫入。

any tips on recognizing the use of properties and not seeing them as simply methods (with the exception of the get;set being apparent) when tracing other peoples code?

的方法應該當返回值預期是動態的每次調用中使用,屬性時,應使用的返回值是不是大動態的。

Any general rules of thumb when it comes to good programming methods in relation to when to use what?

是的,我強烈建議閱讀Framework Design guidelines良好的編程最佳方法。

+0

感謝您對最佳實踐的指導...... – pghtech 2010-06-18 14:17:20

19

1)爲什麼我會想使用性能 代替領域(特別是當它 出現,我只是添加額外的 代碼

你應該總是使用屬性在可能情況下,他們的抽象直接訪問到該字段(如果您不創建一個,則會爲您創建)。即使財產除了設定價值之外別無他法,它仍然可以保護您。稍後將字段更改爲屬性是一項重大改變,因此如果您有公共字段並希望將其更改爲公共屬性,則必須重新編譯最初訪問該字段的所有代碼。

2)承認使用 性質的任何提示,而不是將他們視爲 簡單的方法(與 該得到的異常;設置太明顯),當 跟蹤其他民族的代碼?

我不能完全肯定你所問的,但跟蹤過別人的代碼時,你應該總是假設屬性所做的不僅僅是獲取和設置的值以外的東西。儘管在getter和setter中不要使用大量的代碼是可以接受的,但是你不能僅僅假設它是一個屬性,它會表現得很快。

3)經驗的一般規則,當 涉及到良好的編程方法 關係時使用什麼?

我總是使用屬性來獲取和設置方法,如果可能的話。這樣我可以在以後添加代碼,如果我需要檢查該值是否在某個範圍內,而不是空值等。不使用屬性,我必須返回並將這些檢查放在我直接訪問該字段的每個位置。

0

屬性允許您在使用它們時設置或獲取值以外的其他值。最值得注意的是,它們允許您執行驗證邏輯。

最佳實踐是使任何暴露於公衆的物品成爲物業。這樣,如果稍後更改set/get邏輯,則只需重新編譯您的類,而不是每個與它相關的類。

6

1)有幾個原因,您可能希望使用屬性過場,這裏只是一對夫婦:1)通過

具有以下

public string MyProperty { get; private set; } 

你正在屬性「讀只要」。沒有人使用你的代碼可以修改它的價值。有些情況下,這不是嚴格的(如果你的財產是一個列表),但這些是已知的並且有解決方案。

b)如果你決定你需要增加你的代碼中使用財產的安全:

public string MyProperty 
{ 
    get { return _myField; } 
    set 
    { 
     if (!string.IsNullOrEmpty(value)) 
     { 
      _myField = value; 
     } 
    } 
} 

2)你可以告訴他們屬性,因爲他們沒有()。編譯器會告訴你是否嘗試添加括號。

3)總是使用屬性被認爲是很好的做法。

+1

在VB.NET中,您可以將字段設置爲只讀! – 2010-06-18 13:37:27

+2

@Josh:你也可以在C#中:http://msdn.microsoft.com/en-us/library/acdd6hb7。aspx – LukeH 2010-06-18 13:45:28

+1

@Josh - 'readonly'意味着這個值不能在任何地方改變 - 即使是在同一個班級。使用私有setter屬性意味着您可以修改類中的值,但是您的類的用戶不能。 – ChrisF 2010-06-18 13:58:25

11

關於屬性的好處之一是getter和setter可以有不同的訪問級別。考慮這個:

public class MyClass { 

    public string MyString { get; private set; } 

    //...other code 
} 

此屬性只能從內部,例如在構造函數中更改。閱讀依賴注入。構造函數注入和屬性注入都處理來自某種形式的外部配置的設置屬性。那裏有很多框架。如果您深入瞭解其中的一些內容,您將會對其性能和使用有很好的感受。依賴注入也可以幫助你解決關於良好實踐的第三個問題。

在查看其他人的代碼時,可以通過圖標不同來判斷是方法還是屬性。另外,在Intellisence中,屬性摘要的第一部分是Property。

1

我打算說屬性(setters)是一個很棒的地方,可以引發像NotifyPropertyChanged這樣的事件,但其他人卻把我打敗了。

考慮屬性的另一個很好的理由:比方說,你使用工廠來構造一個具有默認構造函數的對象,並通過它的屬性來準備對象。新建foo(){Prop1 =「bar」,Prop2 = 33,...};

但是,如果外部用戶新增了您的對象,可能是有些屬性需要它們以只讀方式來看,並且無法設置(只有工廠應該可以設置它們)?你可以讓setter成爲內部的 - 當然,如果對象的類與工廠在同一個程序集中,這隻能起作用。

還有其他的方法來實現這一目標,但使用屬性和不同的訪問知名度是一個很好的考慮,如果你正在做基於接口的開發,或者如果你暴露庫給別人,等

5

雖然我絕對不喜歡直接向公衆公開領域,還有一件事:領域不能通過接口暴露;屬性可以。

+1

第一個理智的答案 – 2012-05-19 15:52:10

1

一個警告是,諸如「Threading.Interlocked.Increment」的東西可以與字段一起使用,但不能與屬性一起使用。如果兩個線程同時在SomeObject.LongIntegerField上調用Threading.Interlocked.Increment,則即使沒有其他鎖定,該值也會增加2。相比之下,如果兩個線程同時對SomeObject.LongIntegerProperty調用Threading.Interlocked.Increment,那麼該屬性的值可能會增加2,或1,或-4,294,967,295,或者誰知道其他值(可以寫入屬性在這種情況下使用除一個或兩個以外的鎖定防止值,但無法寫入以確保兩個正確的增量)。

1

使用字段通常在私有類中實現,而不是與其他類共享數據。當我們希望我們的數據可以被其他類訪問時,我們使用能夠與其他類共享數據的屬性,通過getset它們是訪問方法Auto Properties,它們可以訪問私有類中的數據,您也可以在同一個類中同時使用訪問修飾符,從而允許類私有地將數據用作數據字段,並且同時將私有字段鏈接到屬性這使得數據也可以被其他類訪問,請看這個簡單的例子:

private string _name; 
public string Name  
{ 
    get 
    { 
     return _name; 
    } 
    set 
    { 
     _name = value; 
    } 
} 

私有字符串_name僅供類使用,而Name屬性可由同一名稱空間中的其他類訪問。

相關問題