Effective C# Item 8: Ensure That 0 Is a Valid State for Value Types

來源:互聯網
上載者:User

Effective C# Item 8 : Ensure That 0 Is a Valid State for Value Types

      .Net中預設的初始化是將對象的所有資訊都置0。對於實值型別來說,我們不能避免在建立新的實值型別執行個體的時候將其值置為0。這是類型的預設值。

      唯一一個特殊情況是枚舉(enum)。我們不應該建立一個不包含0作為其值的枚舉。所有的枚舉都繼承自System.ValueType。枚舉值是從0開始的,但是我們可以修改它:(P.S. 雖然現在Pluto已經不是太陽系的一員了,bless一下)

public enum Planet
{
      Mercury = 1,
      Venus = 2,
      Earth = 3,
      Mars = 4,
      Jupiter = 5,
      Saturn = 6,
      Neptune = 7,
      Uranus = 8,
      Pluto = 9
}

Planet sphere = new Planet();

      現在sphere的值就是0,這不是一個合法的值。雖然不會報錯,但是0並不代表任何含義。當我們建立自己的引用時,應當確保0是其中的一個枚舉值。如果你將枚舉聲明為二進位類型的,需要定義0來代表None。

      如果這樣發展下去的話,我們只能強迫使用者在初始化的時候就為其明確賦值。

Planet sphere = Planet.Mars;

      這將使得我們很難在其他的類型中使用這種類型,因為我們並不知道要將其初始化為何值。

      使用這樣的類型建立對象將會建立一個不合法的Planet。

ObservationData d = new ObservationData();

      我們必須確保0是一個有效值。如果可以的話應當將其對應為為最佳預設值。對於Planet枚舉來說,沒有什麼最佳可言。當使用者沒有使用的時候,它應當不包含任何含義。我們可以使用0來改造我們的枚舉使其更加合理:

public enum Planet
{
      None = 0,
      Mercury = 1,
      Venus = 2,
      Earth = 3,
      Mars = 4,
      Jupiter = 5,
      Saturn = 6,
      Neptune = 7,
      Uranus = 8,
      Pluto = 9
}

Planet sphere = new Planet();

      sphere現在對應的枚舉值是None,代表還沒有使用者資料。在這裡添加預設值對ObservationData造成的影響就是新初始化的對象的枚舉值是0,代表的含義是None。之後可以在ObservationData的建構函式中對其進行修改。要注意的是預設的建構函式仍然有效。使用者可以構造一個預設值的對象,我們不能阻止他們這樣做。

      在我們結束enum的討論之前,我們還有必要說一下在使用flag的時候枚舉的一些特殊情況。使用Flags屬性時我們應當將代表None含義的枚舉值設為0:(P,S.關於Flags枚舉的情況請看我寫的另一篇介紹:FlagsAttribute屬性在enum中的應用)

[Flags]
public enum Styles
{
      None = 0,
      Flat = 1,
      Sunken = 2,
      Raised = 4
}

      許多開發人員通過二進位操作符&來使用flags枚舉。不合理的0值會造成嚴重的問題,如果flag為0值則下例中的條件會永遠不能成立:

if((flag & Styles.Flat) != 0)
      DoSth();    //如果flag為0則永遠不會執行

      因此如果使用Flags,我們應當確定0代表的含義是None。

      另外的常見初始化問題發生在實值型別中包含的參考型別上。String就是一個常見的例子(P.S. .Net中string是參考型別,雖然某些操作符的重載會給使用者帶來實值型別的錯覺)。

public struct LogMessage
{
      private int _ErrLevel;
      private string _msg;
}

LogMessage MyMessage = new LogMessage();

      MyMessage包含了一個為null的參考型別。這樣並不會引起任何問題。但是當你使用屬性來擷取它的值的時候就可能會出現問題。因此我們要為其添加如果為null則返回string.Empty的邏輯。在我們的結構中我們應當這樣檢驗屬性是否為null。

public struct LogMessage
{
      private int _ErrLevel;
      private string _msg;

      public string Message
      {
            get
            {
                  return(_msg != null)? _msg:string.Empty;
            }
            set
            {
                  _msg = value;
            }
      }
}

      系統初始化時所有的類型的值都為0,這是不能避免的。可能的話應當將0設為最初的預設值。特殊情況下,例如flags枚舉,應當讓其代表None。

      譯自   Effective C#:50 Specific Ways to Improve Your C#                      Bill Wagner著

      回到目錄

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.