c#中單例類與靜態(tài)類的區(qū)別以及使用場景
前言
哈哈,我來了,我又來了,在這年關將至的時候,趁有時間,就多學習和溫習點老的知識。我們在.net core開發(fā)中,會經(jīng)常使用注入來注入一個單例類,而在沒有注入的時候,大部分情況會自己實現(xiàn)一個單例類,或者更簡單的就是實現(xiàn)一個靜態(tài)類。而常常在使用中,都能完成特定的目的,然而它們間的區(qū)別是什么呢?
1.設計模式:單例模式
單例模式:屬于設計模式中創(chuàng)建類型的模式,通過單例模式的方法創(chuàng)建的類,在當前程序中只有一個實例,當然可以實現(xiàn)為線程安全的單例。
這里簡單復習下創(chuàng)建代碼:
1.1 使用時分配,
使用時實例化,多線程應用時,使用不當會有線程安全問題。
public class SingletonA
{
//私有成員,使用時分配內(nèi)存
private static SingletonA _instance = null;
//私有構造,杜絕直接new類
private SingletonA() { }
//獲取實例
public static SingletonA GetInstance ()
{
if (_instance == null)
{
_instance = new SingletonA();
}
return _instance;
}
}
1.2 聲明時實例化
聲明實例時實例化,多線程應用時,使用不當會有線程安全問題。
public class SingletonB
{
//私有靜態(tài)成員,聲明類實例時,分配
private static readonly SingletonB _instance = new SingletonB();
//私有構造,杜絕直接new類
private SingletonB() { }
public static SingletonB GetInstance()
{
return _instance;
}
}
1.3 雙檢鎖
推薦這個,經(jīng)典的線程安全單例實現(xiàn)
public class SingletonD
{
private static SingletonD _instance = null;
private static readonly object _lockObject = new object();
private SingletonD() { }
public static SingletonD GetInstance()
{
if (_instance == null)
{
lock (_lockObject)
{
if (_instance == null)
_instance = new SingletonD();
}
}
return _instance;
}
}
1.4 .net 特性保證的線程安全
最精簡版
public sealed class SingletonC
{
private SingletonC() { }
public static readonly SingletonC Instance = new SingletonC();
}
1.5 使用DI依賴注入時的實現(xiàn)
//FileLogger只需要定義成一般的類即可,無需按照單例模式進行實現(xiàn),當然也不能是靜態(tài)類。
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddSingleton<ILogger, FileLogger>();
}
2. 單例類和靜態(tài)類的比較
我們基于以下幾個要點進行比較
- 是否支持依賴注入
- 內(nèi)存管理是怎樣的
- 可擴展性
- 可測試性
靜態(tài)類形如:
public static class StaticExample
{
private static readonly object lockObj = new object();
public static void Log(string message)
{
//Write code here to log data.
}
}
| 特性比較 | 靜態(tài)類 | 單例類 |
|---|---|---|
| 是否支持依賴注入 | 否,編譯時提示靜態(tài)類型不能作為類型參數(shù) | 支持 |
| 內(nèi)存管理是怎樣的 | 靜態(tài)類存儲在托管堆的high frequency heap,僅當應用程序卸載時,才釋放內(nèi)存 | 單例類的單個實例是靜態(tài)的,因此也保存在high frequency heap,當應用程序卸載時,才釋放內(nèi)存。但是,與只能具有靜態(tài)對象的靜態(tài)類不同,單例類可以同時具有靜態(tài)和非靜態(tài)對象。因此,從內(nèi)存管理的角度來看,當您使用單例類時,可以利用垃圾回收管理對象。 |
| 可擴展性 | 您不能繼承靜態(tài)類并覆蓋其方法 ;靜態(tài)類不能具有擴展方法 | 單例類通常包含一個私有構造函數(shù),并標記為已密封,以指示它既不能實例化也不能繼承;因此,只有在單例類中具有非私有構造函數(shù)的情況下,才可以擴展單例類;單例類可以具有擴展方法 |
| 可測試性 | 模擬靜態(tài)類非常困難,特別是在包含靜態(tài)對象的時候。當然如果是只有靜態(tài)方法,且冪等則還是很容易測試的 | 測試單例類很容易 |
3.使用場景
經(jīng)過上面的對比,你應該看出端倪了。

當您只需要一個包含多個方法的工具類時,靜態(tài)類是一個不錯的選擇,在這種情況下您不需要實例。因為您沒有此類的任何實例,所以這個簡單的實現(xiàn)提高了應用程序的性能。
單例模式可用于設計只需要一個實例的類。典型示例包括用于日志記錄,緩存,線程池等的管理器類,在這些場景,單例類是一個不錯的選擇。為此,您應該有一個實例,以避免對同一資源的請求沖突。
還有在引入了DI框架后,你應該多多使用單例類,因為實現(xiàn)這樣的需求,就是簡單的定義一個普通的類,然后注冊到DI中即可。
當然還有一點就是單例類更加像面向?qū)ο缶幊?,哈哈~~~
總結
到此這篇關于c#中單例類與靜態(tài)類的區(qū)別以及使用場景的文章就介紹到這了,更多相關c#單例類與靜態(tài)類的區(qū)別及使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C#使用DevExpress中的XtraCharts控件實現(xiàn)圖表
這篇文章介紹了C#使用DevExpress中的XtraCharts控件實現(xiàn)圖表的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05
ItemsControl 數(shù)據(jù)綁定的兩種方式
這篇文章主要介紹了ItemsControl 數(shù)據(jù)綁定的兩種方式,幫助大家更好的理解和學習使用c#,感興趣的朋友可以了解下2021-03-03
淺談Visual Studio 2019 Vue項目的目錄結構
這篇文章主要介紹了Visual Studio 2019 Vue項目 目錄結構,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03

