最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#實現(xiàn)單例模式的幾種方法總結(jié)

 更新時間:2021年01月15日 09:20:18   作者:zls365  
這篇文章主要介紹了C#實現(xiàn)單例模式的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

介紹

單例模式是軟件工程學(xué)中最富盛名的設(shè)計模式之一。從本質(zhì)上看,單例模式只允許被其自身實例化一次,且向外部提供了一個訪問該實例的接口。通常來說,單例對象進(jìn)行實例化時一般不帶參數(shù),因為如果不同的實例化請求傳遞的參數(shù)不同的話會導(dǎo)致問題的產(chǎn)生。(若多個請求都是傳遞的同樣的參數(shù)的話,工廠模式更應(yīng)該被考慮)

C#中實現(xiàn)單例有很多種方法,本文將按順序介紹非線程安全、完全懶漢式、線程安全和低/高性能集中版本。

在所有的實現(xiàn)版本中,都有以下幾個共同點:

  • 唯一的、私有的且無參的構(gòu)造函數(shù),這樣不允許外部類進(jìn)行實例化;
  • 類是密封的,盡管這不是強制的,但是嚴(yán)格來講從上一點來看密封類能有助于JIT的優(yōu)化;
  • 一個靜態(tài)變量應(yīng)該指向類的唯一實例;
  • 一個公共的靜態(tài)變量用于獲得這個類的唯一實例(如果需要,應(yīng)該創(chuàng)建它);

需要注意的是,本文中所有的例子中都是用一個 public static Instance的變量來訪問單例類實例,要將其轉(zhuǎn)換成公共函數(shù)是很容易的,但是這樣并不會帶來效率和線程安全上的提升。

Version 1 - 非線程安全

/// <summary>
/// Bad code!Do not use! 
/// </summary>
public sealed class Singleton
{
 private static Singleton instance = null;
 private Singleton() { }
 public static Singleton Instance
 {
  get
  {
   if (instance == null)
   {
    instance = new Singleton();
   }
   return instance;
  }
 }
}

該版本在多線程下是不安全的,會創(chuàng)建多個實例,請不要在生產(chǎn)環(huán)境中使用!

因為如果兩個線程同時運行到if(instance==null)判斷時,就會創(chuàng)建兩個實例,這是違背單例模式的初衷的。實際上在后面那個線程進(jìn)行判斷是已經(jīng)生成了一個實例,但是對于不同的線程來說除非進(jìn)行了線程間的通信,否則它是不知道的。

Version 2 - 簡單的線程安全

public sealed class Singleton2
{
 private static Singleton2 instance = null;
 private static readonly object obj = new object();
 private Singleton2() { }
 public Singleton2 Instance
 {
  get
  {
   lock (obj)
   {
    if (instance == null)
    {
     instance = new Singleton2();
    }
    return instance;
   }
  }
 }
}

該版本是線程安全的。通過對一個過線程共享的對象進(jìn)行加鎖操作,保證了在同一時刻只有一個線程在執(zhí)行l(wèi)ock{}里的代碼。當(dāng)?shù)谝粋€線程在進(jìn)行instance判斷或創(chuàng)建時,后續(xù)線程必須等待直到前一線程執(zhí)行完畢,因此保證了只有第一個線程能夠創(chuàng)建instance實例。

但不幸的是,因為每次對instance的請求都會進(jìn)行l(wèi)ock操作,其性能是不佳的。

需要注意的是,這里使用了一個private static object變量進(jìn)行鎖定,這是因為當(dāng)如果對一個外部類可以訪問的對象進(jìn)行鎖定時會導(dǎo)致性能低下甚至死鎖。因此通常來說為了保證線程安全,進(jìn)行加鎖的對象應(yīng)該是private的。

Version 3 - Double-check locking的線程安全

/// <summary>
/// Bad code ! Do not use!
/// </summary>
public sealed class Singleton3
{
 private static Singleton3 instance = null;
 private static object obj = new object();
 private Singleton3() { }
 public static Singleton3 Instance
 {
  get
  {
   if (instance == null)
   {
    lock (obj)
    {
     if (instance == null)
     {
      instance = new Singleton3();
     }
    }
   }
   return instance;
  }
 }
}

該版本中試圖去避免每次訪問都進(jìn)行加鎖操作并實現(xiàn)線程安全。然后,這段代碼對Java不起作用,因Java的內(nèi)存模型不能保證在構(gòu)造函數(shù)一定在其他對象引用instance之前完成。還有重要的一點,它不如后面的實現(xiàn)方式。

Version 4 - 不完全懶漢式,但不加鎖的線程安全

public sealed class Singleton4
{
 private static readonly Singleton4 instance = new Singleton4();
 /// <summary>
 /// 顯式的靜態(tài)構(gòu)造函數(shù)用來告訴C#編譯器在其內(nèi)容實例化之前不要標(biāo)記其類型
 /// </summary>
 static Singleton4() { }
 private Singleton4() { }
 public static Singleton4 Instance
 {
  get
  {
   return instance;
  }
 }
}

這個版本是的實現(xiàn)非常的簡單,但是卻又是線程安全的。C#的靜態(tài)構(gòu)造函數(shù)只有在當(dāng)其類的實例被創(chuàng)建或者有靜態(tài)成員被引用時執(zhí)行,在整個應(yīng)用程序域中只會被執(zhí)行一次。使用當(dāng)前方式明顯比前面版本中進(jìn)行額外的判斷要快。

當(dāng)然這個版本也存在一些瑕疵:

不是真正意義上的懶漢模式(需要的時候才創(chuàng)建實例),若單例類還存在其他靜態(tài)成員,當(dāng)其他類第一次引用這些成員時便會創(chuàng)建該instance。下個版本實現(xiàn)會修正這個問題;

只有.NET中才具有beforefieldinit特性,即懶漢式實現(xiàn)。且在.Net 1.1以前的編譯器不支持,不過這個現(xiàn)在來看問題不大;

所有版本中,只有這里將instance設(shè)置成了readonly,這不僅保證了代碼的高校且顯得十分短小。

Version 5 - 完全懶漢實例化

public sealed class Singleton5
{
 private Singleton5() { }
 public static Singleton5 Instance { get { return Nested.instance; } }
 private class Nested
 {
  //Explicit static constructor to tell C# compiler
  //not to mark type as beforefieldinit
  static Nested()
  {
  }
  internal static readonly Singleton5 instance = new Singleton5();
 }
}

該版本看起來稍微復(fù)雜難懂,其實只是在寫法上實現(xiàn)了上一版本的瑕疵,通過內(nèi)嵌類的方式先實現(xiàn)了只有在真正應(yīng)用Instance時才進(jìn)行實例化。其性能表現(xiàn)與上一版本無異。

Version 6 - 使用.NET 4 Lazy<T> type 特性

public sealed class Singleton6
{
 private static readonly Lazy<Singleton6> lazy =
   new Lazy<Singleton6>(()=> new Singleton6());
 public static Singleton6 Instance { get { return lazy.Value; } }
 private Singleton6() { }
}

如果你使用的是.NET 4或其以上版本,可以使用System.Lazy<T> type來實現(xiàn)完全懶漢式。其代碼看起來也很簡潔且性能表現(xiàn)也很好。

性能 VS 懶漢式

一般情況下,我們并不需要實現(xiàn)完全懶漢式,除非你的構(gòu)造初始化執(zhí)行了某些費時的工作。因此一般的,我們使用顯式的靜態(tài)構(gòu)造函數(shù)就能夠適用。

本文翻譯自Implementing the Singleton Pattern in C#, 作者在文中做了一些循環(huán)測試,具體的讀者可直接閱讀原文。

Exception

有時候在進(jìn)行構(gòu)造函數(shù)初始化時可能 會拋出異常,但這對整個應(yīng)用程序來說不應(yīng)該是致命的,所以可能的情況下,你應(yīng)該自己處理這種異常情況。

總結(jié)

上述提供的幾種實現(xiàn)方法中,一般情況下提倡使用Version 4,除非遇到有時早于單列類實例化時就引用了其他靜態(tài)成員。這種情況下,Version 2一旦被考慮,雖然它看起來會因加鎖耗時,但是其實運行起來并沒有你想的那么慢,關(guān)鍵是你很容易寫對它。

顯然Version 1你永遠(yuǎn)都不應(yīng)該考慮,Version 3在與Version 5的對比下也是不在考慮范圍之內(nèi)的。

到此這篇關(guān)于C#實現(xiàn)單例模式的文章就介紹到這了,更多相關(guān)C#實現(xiàn)單例模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 理解C#中的事件

    理解C#中的事件

    這篇文章主要介紹了理解C#中的事件,本文講解了使用委托中的問題、事件的出現(xiàn)、深入理解事件、C#屬性的概念、事件代碼的轉(zhuǎn)換等內(nèi)容,需要的朋友可以參考下
    2015-02-02
  • C#中計時器的簡單實現(xiàn)方法示例

    C#中計時器的簡單實現(xiàn)方法示例

    這篇文章主要介紹了C#中計時器的簡單實現(xiàn)方法,結(jié)合實例形式分析了C#計時器的簡單定義與使用技巧,需要的朋友可以參考下
    2017-05-05
  • C#格式化數(shù)字字符串的方法

    C#格式化數(shù)字字符串的方法

    這篇文章主要為大家詳細(xì)介紹了C#格式化數(shù)字字符串的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • C#讀取數(shù)據(jù)庫返回泛型集合詳解(DataSetToList)

    C#讀取數(shù)據(jù)庫返回泛型集合詳解(DataSetToList)

    本篇文章主要是對C#讀取數(shù)據(jù)庫返回泛型集合(DataSetToList)進(jìn)行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01
  • C#獲取CPU處理器核心數(shù)量的方法

    C#獲取CPU處理器核心數(shù)量的方法

    本文主要介紹了C#獲取CPU處理器核心數(shù)量的方法,代碼簡單易懂,具有很好的參考價值,需要的朋友可以看下
    2016-12-12
  • 總結(jié)C#處理異常的方式

    總結(jié)C#處理異常的方式

    這篇文章介紹了C#處理異常的方式總結(jié),文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • c#多種加解密示例(md5加密解密)

    c#多種加解密示例(md5加密解密)

    這篇文章主要介紹了c#多種加解密示例,包括了MD5加密,SHA1加密,DES加解密,需要的朋友可以參考下
    2014-03-03
  • C# List介紹及具體用法

    C# List介紹及具體用法

    這篇文章主要介紹了C# List介紹及具體用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • C#可變參數(shù)params示例詳解

    C#可變參數(shù)params示例詳解

    params是c#的一個關(guān)鍵字,用用漢語來說的話叫可變參數(shù),這里的可變,不是說的類型可變,而是指的個數(shù)可變,這是c#的一個基礎(chǔ)關(guān)鍵字,相信大家都有一定的了解,本篇文章就來大致的說一下C#可變參數(shù)params
    2022-02-02
  • C# DataGridView添加新行的2個方法

    C# DataGridView添加新行的2個方法

    DataGridView控件在實際應(yīng)用中非常實用,特別需要表格顯示數(shù)據(jù)時。
    2013-03-03

最新評論

子洲县| 油尖旺区| 杨浦区| 荃湾区| 河北省| 巴林左旗| 西平县| 陇西县| 五原县| 循化| 福安市| 清镇市| 石泉县| 开平市| 伊通| 南陵县| 永清县| 崇信县| 崇文区| 南溪县| 平度市| 博客| 微博| 怀化市| 呼伦贝尔市| 鄂托克前旗| 和硕县| 蕲春县| 汝州市| 洛南县| 进贤县| 五寨县| 安仁县| 安丘市| 巍山| 胶州市| 湘西| 商丘市| 铜鼓县| 图木舒克市| 灌南县|