Effective C# 原則13:用靜態建構函式初始化類的靜態成員(譯)

來源:互聯網
上載者:User

Effective C# 原則13:用靜態建構函式初始化類的靜態成員
Item 13: Initialize Static Class Members with Static Constructors
(譯註:initializer在上文中譯為了“初始化器”,實在不好聽,本文中全部改譯為:“預置方法”)
你應該知道,在一個類型的任何執行個體初始化以前,你應該初始化它的靜態成員變數。在裡C#你可以使用靜態預置方法和靜態建構函式來實現這個目的。一個類的靜態建構函式是一個與眾不同的,它在所有的方法,變數或者屬性訪問前被執行。你可以用這個函數來初始化靜態成員變數,強制使用單件模式,或者實現其它任何在類型的執行個體可用前應該完成的工作。你不能用任何的執行個體建構函式,其它特殊的私人函數, 或者任何其它習慣方法來初始化一個 變數(譯註:編譯器就不讓你這樣做,所以你不用擔心這樣的問題)。

和執行個體的預置方法一樣,你可以把靜態預置方法做為靜態建構函式可替代的選擇。如果須要簡單的分配一個靜態成員,就直接使用初始化文法。當你有更複雜的邏輯來初始化靜態成員變數時,就建立一個靜態建構函式:

public class MySingleton
{
  private static readonly MySingleton _theOneAndOnly =
    new MySingleton( );

  public static MySingleton TheOnly
  {
    get
    {
      return _theOneAndOnly;
    }
  }

  private MySingleton( )
  {
  }

  // remainder elided
}

可以用下面的方法簡單的實現單件模式,實際上你在初始化一個單件模式時可能有更複雜的邏輯:
public class MySingleton
{
  private static readonly MySingleton _theOneAndOnly;

  static MySingleton( )
  {
    _theOneAndOnly = new MySingleton( );
  }

  public static MySingleton TheOnly
  {
    get
    {
      return _theOneAndOnly;
    }
  }

  private MySingleton( )
  {
  }

  // remainder elided
}

同樣,和執行個體的預置方法一樣,靜態預置方法在靜態建構函式調用前執行。並且,你的靜態預置方法在基類的靜態建構函式執行前被執行。

當應用程式第一次裝載你的資料類型時,CLR自動調用靜態建構函式。你只能定義一個靜態建構函式,並且不能有參數。因為靜態建構函式是CLR調用的,你必須十分注意異常的產生。如果在靜態建構函式裡產生了異常,CLR將會直接終止你的應用程式。正因為異常,靜態建構函式常常代替靜態預置方法。如果你使用靜態預置方法,你自己不能捕獲異常。做為一個靜態構造,你可以這樣(參見原則45):
static MySingleton( )
{
  try {
    _theOneAndOnly = new MySingleton( );
  } catch
  {
    // Attempt recovery here.
  }
}

靜態預置方法和靜態建構函式為你的類提供了最清爽的方法來初始化靜態成員。與其它語言不同,它們被添加到C#語言中,是初始化靜態成員的兩個不同的特殊位置。

===================

Item 13: Initialize Static Class Members with Static Constructors
You know that you should initialize static member variables in a type before you create any instances of that type. C# lets you use static initializers and a static constructor for this purpose. A static constructor is a special function that executes before any other methods, variables, or properties defined in that class are accessed. You use this function to initialize static variables, enforce the singleton pattern, or perform any other necessary work before a class is usable. You should not use your instance constructors, some special private function, or any other idiom to initialize static variables.

As with instance initialization, you can use the initializer syntax as an alternative to the static constructor. If you simply need to allocate a static member, use the initializer syntax. When you have more complicated logic to initialize static member variables, create a static constructor.

Implementing the singleton pattern in C# is the most frequent use of a static constructor. Make your instance constructor private, and add an initializer:

public class MySingleton
{
  private static readonly MySingleton _theOneAndOnly =
    new MySingleton( );

  public static MySingleton TheOnly
  {
    get
    {
      return _theOneAndOnly;
    }
  }

  private MySingleton( )
  {
  }

  // remainder elided
}

The singleton pattern can just as easily be written this way, in case you have more complicated logic to initialize the singleton:

public class MySingleton
{
  private static readonly MySingleton _theOneAndOnly;

  static MySingleton( )
  {
    _theOneAndOnly = new MySingleton( );
  }

  public static MySingleton TheOnly
  {
    get
    {
      return _theOneAndOnly;
    }
  }

  private MySingleton( )
  {
  }

  // remainder elided
}

As with instance initializers, the static initializers are called before any static constructors are called. And, yes, your static initializers execute before the base class's static constructor.

The CLR calls your static constructor automatically when your type is first loaded into an application space. You can define only one static constructor, and it must not take any arguments. Because static constructors are called by the CLR, you must be careful about exceptions generated in them. If you let an exception escape a static constructor, the CLR will terminate your program. Exceptions are the most common reason to use the static constructor instead of static initializers. If you use static initializers, you cannot catch the exceptions yourself. With a static constructor, you can (see Item 45):

static MySingleton( )
{
  try {
    _theOneAndOnly = new MySingleton( );
  } catch
  {
    // Attempt recovery here.
  }
}

Static initializers and static constructors provide the cleanest, clearest way to initialize static members of your class. They are easy to read and easy to get correct. They were added to the language to specifically address the difficulties involved with initializing static members in other languages.
 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.