簡體   English   中英

正確使用C#屬性

[英]Correct use of C# properties

private List<Date> _dates;

public List<Date> Dates
{
    get { return _dates; }
    set { _dates = value; }
}

要么

public List<Date> Dates
{
    get;        
    set;    
}

我一直使用前者,這是不正確還是不好的做法? 我從沒想到我可以使用第二種選擇。 我喜歡讓我的封裝變量以下划線開頭,因此可以將它們與方法參數區分開。 我一直都是那樣做的。

使用第一個選項是否有可能導致實例化一個額外的List<Date>對象,然后將整個_dates替換為value ,或者比這更聰明?

另外,哪個行業最突出或完全主觀?

如果您需要在getter / setter方法中添加某種邏輯,請使用前者。

否則使用后者。 它使事情變得更加清潔。 您還可以使用自動屬性來實現只讀屬性:

public List<Date> Dates { get; private set; }

或者,如果您不希望人們通過該屬性將任何項目添加到列表中,則可以采用前一種語法:

private List<Date> _dates = new List<Date>();
private ReadOnlyCollection<Date> _readOnlyDates =
    new ReadOnlyCollection<Date>(_dates);

public ReadOnlyCollection<Date> Dates
{
    get { return _readOnlyDates; }
}

由於.NET如何編譯自動屬性,因此兩者基本上是相同的。 .NET 3.5提供了自動屬性。

它們在內部編譯形式中是等效的,除了您不能以第二種形式訪問編譯器生成的私有變量。

從代碼效率的角度來看,它們也是等效的,即時編譯器通常直接訪問私有變量,而沒有調用訪問函數的開銷(在運行時環境檢查了可訪問性之后)。

從編碼的角度來看,我更喜歡第二個版本,它更緊湊(更少的編寫,更少的閱讀)。

第二種語法在C#3.0中引入。 因此,第一種變體將與舊編譯器更兼容。

我傾向於更多地使用自動屬性,因為屬性是表達您的對象正在執行的操作的一種好方法,但仍然具有一定的保護作用。

我幾乎所有的屬性聲明如下:

public bool IsBlah { get; private set; }

這使其成為一個不錯的,可讀的和受保護的吸氣劑。

但是有時您需要顯式的后備字段:

private bool? _isBlah;
public bool IsBlah
{
    get
    {
        if (_isBlah == null)
        {
            // Do something expensive here and set _isBlah
            _isBlah = true;
        }
        return _isBlah;
    }
}

前者是原始方法,后者是較新的“自動屬性”功能的示例,編譯器通過該功能自動為您生成一個后備字段。

有些人(包括我自己)回避自動屬性,因為語法很容易被誤認為抽象屬性,沒有用於“只讀”屬性的功能,並且帶有私有設置器的自動屬性的語法很笨拙:

public List Dates
{
    get;
    private set;
}

我還發現讓類的內​​部實現通過類API訪問字段很不舒服。

第二種變化稱為自動實現的屬性 ,是C#3.0中引入的(因此您以前可能沒有遇到過這種情況)。

如果要創建具有后備字段的簡單屬性並且不需要在“ getter”和“ setter”中實現任何邏輯,則最好使用此格式。 它不僅更加簡潔,而且還迫使您直接訪問該屬性,而不是通過通常是最佳實踐的背景進行訪問。

注意,您仍然可以初始化屬性,只需通過構造函數即可。

public class MyClass
{

  public List<Date> Dates
  {
      get;        
      set;    
  }

  public MyClass()
  {
      Dates = new List<Date>();
  }

}

我個人更喜歡第一種方法,因為它允許您在返回之前執行一些操作。

EG(一個非常糟糕的例子)

    private int _limit;
    private int _onHand;
    private bool returnToVendor;

    public Item(int limit, int onHand)
    {
       _limit = limit;
       _onHand = onHand;
    }

    public int ReturnStock
    {
       get
       {
         if(_onHand > _limit)
         {
            returnToVendor = true;
            return _onHand;
         }
       }

       set
       {
           _onHand = value;

           if(_onHand < _limit)
           {
              returnToVendor = false;
           }
       }
    }

沒關系 第二個就是糖。 我總是使用第二個,因為它更干凈,但是我偶爾需要訪問支持值。

只要您不必確保在getter中初始化List<Date>就可以使用這兩個版本。 我只是建議您使用一個版本,並且不要在代碼中混用它。

如果需要初始化,則必須使用第一個版本...

private List<Date> _dates; 

public List<Date> Dates 
{ 
    get { if (_dates == null) _dates = new List<Date>(); return _dates; } 
    set { _dates = value; } 
} 

我相信它們可以編譯為相同的代碼。 后者只是表示前者的語法糖。 我傾向於將后者視為將來邏輯的占位符,可能需要將其放置在屬性中,此時,我將把受影響的屬性轉換為前者。

兩者的編譯方式大致相同(我不知道背景字段的名稱將完全相同,但在功能上是等同的)。

IIRC在.NET 3.0或3.5中添加了執行自動屬性( public List<Date> Dates {get; set;} )的功能。

據我所記得,我一直在對象內部管理列表屬性,使它們成為只讀。

private IList<DateTime> _dates;

public MyClass() {
    _dates = new List<DateTime>();
}

public IList<DateTime> Dates {
    get {
        return _dates;
    }
}

這樣,我確保我訪問列表時永遠不會為空,因為客戶端無法分配它。

但是,對於您的示例,僅在獲取或設置屬性時需要某種邏輯時才需要使用前一種方法。 否則,自動屬性的作用與您完全相同,只是獲取並設置一個私有字段的值。 此外, { get; set; } { get; set; } { get; set; }以我的謙卑觀點,可以提高可讀性並幫助其他程序員理解您的意圖。

例如:

public class MyClass {
    private IList<DateTime> _dates;

    public IList<DateTime> Dates {
        get {
            return _dates;
        } set {
            _dates = value;
        } 
    }
}

public class MyClasse {
    public IList<DateTime> Dates { get; set; }
}

第二種方法至少對我而言使意圖更精簡和快捷。 當不需要在getter和setter內部使用邏輯時,編寫類的代碼將變得更快。

否則,一個不比另一個更好,並且做得完全一樣,說到獲取和設置該屬性的值而沒有邏輯。

最重要的是,您需要熟悉您的代碼。 如果最終結果是您沒有獲得任何改進,並且您喜歡自己在做什么,那么就不僅僅要做。 =)

暫無
暫無

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

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