簡體   English   中英

為什么要使用字段而不是屬性?

[英]Why ever use fields instead of properties?

我對C#很新,我認為屬性是一件很棒的事情。 事實上,如此精彩,我看不到使用字段的任何真正優勢。 即使對於私人領域,性能提供的靈活性和模塊性似乎最多可以避免嚴重的麻煩,最糟糕的是根本沒有效果。

我可以在字段中看到的唯一優勢是您可以內聯初始化它們。 但是大多數時候,你想在構造函數中初始化它們。 如果您不使用內聯初始化,是否有任何理由不使用屬性?

編輯:有些人提出需要使用字段備份屬性(顯式或自動)。 讓我們澄清一下我的問題: 除了備份屬性之外,有沒有理由使用字段? 即, SomeType someField;有沒有時間SomeType someField; 優於SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; }

編輯2:DanM,Skurmedel和Seth都提供了非常有用的答案。 我已經接受了DanM,因為它是最完整的,但如果有人將他們的回答總結為一個答案,我會很樂意接受它。

通常,屬性需要一個支持字段,除非它們是簡單的getter / setter“自動屬性”。

所以,如果你只是......

public string Name { get; set; } // automatic property

......你不需要一個領域,我同意,沒有理由擁有一個領域。

但是,如果你正在......

public string Name
{
    get { return _name; }
    set 
    {
       if (value = _name) return;
       _name = value;
       OnPropertyChange("Name");
    }
}

...你需要_name支持字段。

對於不需要任何特殊get / set邏輯的私有變量,它實際上是一個判斷調用,無論是私有自動屬性還是只是一個字段。 我通常做一個字段,然后,如果我需要protectedpublic ,我會將其更改為自動屬性。

更新

正如Yassir所指出的,如果你使用自動屬性,那么幕后仍然會有一個潛伏的場地,這不是你實際需要輸入的東西。 因此,底線是:屬性不存儲數據,它們提供對數據的訪問。 字段是實際保存數據的內容。 所以,即使你看不到它們,你也需要它們。

更新2

關於你修改過的問題......

有沒有時間SomeType someField; 優於SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; }

...有一件事情會浮現在腦海中:如果您有一個私有字段,並且(根據私有字段的慣例),您將其稱為_name ,它會向您和正在閱讀您的代碼的任何人發出信號,表明您正在使用私有數據。 另一方面,如果你把所有東西都作為屬性,並且(根據屬性的約定)調用你的私有屬性Name ,現在你不能只看變量並告訴它是私有數據。 因此,僅使用屬性會刪除一些信息。 我沒有嘗試過與所有房產合作來衡量這是否是關鍵信息,但肯定會丟失一些東西。

另一個更小的問題是public string Name { get; set; } public string Name { get; set; } public string Name { get; set; }需要更多的輸入(並且是有點混亂),比private string _name

屬性是一件很棒的事情 - 但是存在與屬性訪問相關的開銷。 不一定是問題,但需要注意的事項。

避免過度使用財產吸氣劑和二傳手

大多數人都沒有意識到,在開銷方面,屬性getter和setter與方法類似; 它主要是區分它們的語法。 除了字段訪問之外不包含任何指令的非虛擬屬性getter或setter將由編譯器內聯,但在許多其他情況下,這是不可能的。 你應該仔細考慮你對財產的使用; 從類內部直接訪問字段(如果可能),並且從不盲目地重復調用屬性而不將值存儲在變量中。 總而言之,這並不意味着你應該使用公共領域!

資料來源: http//dotnet.sys-con.com/node/46342

在使用ref / out args時嘗試使用Property:

someObject.SomeMethod(ref otherObject.SomeProperty);

它不會編譯。

如果你想要readonly一些東西,你幾乎必須使用一個字段,因為沒有辦法告訴自動屬性生成一個只讀字段。

我經常這樣做。

舉例:

class Rectangle
{
   private readonly int _width;
   private readonly int _height;

   public Rectangle(int width, int height)
   {
      _width = width;
      _height = height;
   }

   public int Width { get { return _width; } }
   public int Height { get { return _height; } }
}

這意味着Rectangle內部的任何內容都不能改變構造后的寬度或高度。 如果一個人試圖編譯器會抱怨。

如果我使用私有setter的自動屬性,編譯器將不會保護我自己。

我看到的另一個原因是,如果不需要公開一些數據(保持private ),為什么要將其作為財產?

雖然我同意我認為大衛·巴薩拉布的聲明中的“意圖”:“沒有理由公開曝光字段,”我想補充一點略有不同:

我將以上大衛的引用修改為:“除了通過有意識地選擇封裝嚴格控制訪問的屬性中的字段之外,沒有理由公開暴露字段......在類之外......

字段不僅僅是字段“貼在”C#上的“單板”:它們是一個基本的語言功能,其設計理由很充分,包括:

  1. 控制暴露的內容而不暴露在類外(封裝,數據隱藏)

  2. 允許在訪問或設置屬性時執行某些操作:最好在屬性“獲取和”設置中表達的操作,而不是“提升”到外部定義的方法。

  3. 按設計的接口不能定義'字段:但可以定義屬性。

良好的OO設計意味着對“狀態”進行有意識的選擇:

  1. 局部變量字段:什么狀態是方法和瞬態的私有狀態:局部變量通常僅在方法體的范圍內有效,或者甚至在“for循環”范圍內具有“縮短生命周期”。 當然,您也可以將方法中的參數變量視為“本地”。

  2. 類實例字段:什么狀態是類的私有狀態,並且對於類的每個實例都是獨立存在的,但很可能需要在類的多個位置使用。

  3. 靜態實例字段:什么狀態只是類的屬性,與類的實例數無關。

  4. 故意並有意識地暴露出類“外部”:關鍵的想法是在類和本類公開的數據的“消費者”之間插入至少一個間接層。 當然,“曝光”的“反面”是隱藏(封裝,隔離)實現代碼的意圖。

    一個。 通過公共財產:這里所有其他答案都涵蓋了這方面的所有方面

    通過索引器

    C。 通過方法

    d。 公共靜態變量通常位於實用程序類中,通常是靜態類。

建議你回顧: MSDN on'Fields ... MSDN on Properties ... MSDN on Indexers

我不明白你為什么要使用私人autoproperties。 那有什么好處

private int Count {get; set;}

過度

private int count

沒有理由公開曝光字段。

如果您公開公開某個字段,則無法更改信息來源,從內聯定義到配置文件而不進行重構。

您可以使用字段隱藏內部數據。 我很少贊成這一點,當我做一些公開隱藏並在房產中使用它時,我只使用字段。 (即我沒有使用自動屬性生成)

字段是您可以存儲州的唯一地方。 屬性實際上只是一對具有特殊語法的方法,允許它們根據它們的使用方式映射到get或set方法:如果屬性修改或訪問狀態,該狀態仍然必須存儲在字段中。

你並不總是看到這些字段。 使用C#3自動屬性,編譯器將為您創建該字段。 但它仍然存在。 此外,自動屬性具有一些顯着的局限性(例如,沒有INotifyPropertyChanged支持,在setter中沒有業務邏輯),這意味着它們通常是不合適的,並且您無論如何都需要創建顯式字段和手動定義的屬性。

根據David的回答 ,如果您正在討論API,那么您就是對的:您幾乎從不想讓內部狀態(字段)成為API的一部分。

字段的語法比寫入屬性要快得多,所以當使用字段(對類私有)時,為什么不使用它並保存額外的輸入呢? 如果自動實現的屬性具有簡潔的簡潔語法,並且您不得不做額外的工作來創建一個普通的舊字段,那么人們可能只是開始使用屬性。 此外,它現在是C#的慣例。 這就是人們的思考方式,也是他們期望在代碼中看到的東西。 如果你做了與平常不同的事情,你會混淆每個人。

但是你可以問為什么字段的語法不會創建一個自動實現的屬性而不是一個字段,所以你可以充分利用這兩個世界 - 各地的屬性和簡潔的語法。

有一個非常簡單的原因,我們仍然需要有明確的字段:

C#1.0沒有我們現在擁有的所有這些優秀功能,因此字段是生活中的事實 - 如果沒有它們,你就無法生存。 許多代碼依賴於字段和屬性是明顯不同的東西。 在不破壞大量代碼的情況下,它現在無法更改。

我還懷疑存在性能影響,但也許可以通過抖動來解決。

所以我們永遠堅持使用字段,因為它們在那里並且它們采用了最好的語法,所以在安全的情況下使用它們是有意義的。

字段和屬性不可互換。 我猜你所說的是通過私有財產訪問私人領域。 我這樣做是有意義的,但在大多數情況下,沒有必要。 在大多數情況下,JIT優化器將通過私有屬性內聯訪問私有字段。 由於私有成員不是您的界面的一部分,因此將私有字段包裝在私有財產中不會被視為重大變更。

就個人而言,我永遠不會暴露任何受保護/公共實例字段。 雖然只要字段類型本身是不可變的,但通常使用只讀修飾符公開公共靜態字段是可以接受的。 這通常出現在SomeStruct.Empty靜態字段中。

正如其他人所指出的那樣,無論如何你都需要一個私人支持領域。

在屬性上使用字段也有速度優勢。 在99.99%的情況下,這無關緊要。 但有些可能會。

速度。 如果在模擬過程中字段被設置或讀取數十億次,那么您希望使用字段而不是屬性來避免子例程調用的開銷。 盡可能符合OO(DDD?),在這些情況下,我建議僅在專門用於表示某種“價值”的類中使用字段。 邏輯應該保持在最低限度。 相反,有一個人或者一個人。

但如果你有這些問題,那么你可能不是編程c ++而不是c#,不是嗎?

@Seth有幾個好的(部分)答案(字段表現更好,因此在私人環境中你可能會在有意義的時候使用它),@ Skurmedel(字段可以只讀),@ Jenk(字段可以用於ref / out)。 但是我想補充一點:

您可以使用簡化的初始化語法來設置字段的值,但不能使用屬性。 即:

private int x = 7;

VS

private int x { get; set; }

// This must go in the constructor, sometimes forcing you to create 
// a constructor that has no other purpose.
x = 7;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM