c#中單例類與靜態類的區別以及使用場景
阿新 • • 發佈:2021-01-11
前言
哈哈,我來了,我又來了,在這年關將至的時候,趁有時間,就多學習和溫習點老的知識。我們在.net core開發中,會經常使用注入來注入一個單例類,而在沒有注入的時候,大部分情況會自己實現一個單例類,或者更簡單的就是實現一個靜態類。而常常在使用中,都能完成特定的目的,然而它們間的區別是什麼呢?
1.設計模式:單例模式
單例模式:屬於設計模式中建立型別的模式,通過單例模式的方法建立的類,在當前程式中只有一個例項,當然可以實現為執行緒安全的單例。
這裡簡單複習下建立程式碼:
1.1 使用時分配,
使用時例項化,多執行緒應用時,使用不當會有執行緒安全問題。
public class SingletonA { //私有成員,使用時分配記憶體 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 { //私有靜態成員,宣告類例項時,分配 private static readonly SingletonB _instance = new SingletonB(); //私有構造,杜絕直接new類 private SingletonB() { } public static SingletonB GetInstance() { return _instance; } }
1.3 雙檢鎖
推薦這個,經典的執行緒安全單例實現
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依賴注入時的實現
//FileLogger只需要定義成一般的類即可,無需按照單例模式進行實現,當然也不能是靜態類。 public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddSingleton<ILogger,FileLogger>(); }
2. 單例類和靜態類的比較
我們基於以下幾個要點進行比較
- 是否支援依賴注入
- 記憶體管理是怎樣的
- 可擴充套件性
- 可測試性
靜態類形如:
public static class StaticExample { private static readonly object lockObj = new object(); public static void Log(string message) { //Write code here to log data. } }
特性比較 | 靜態類 | 單例類 |
---|---|---|
是否支援依賴注入 | 否,編譯時提示靜態型別不能作為型別引數 | 支援 |
記憶體管理是怎樣的 | 靜態類儲存在託管堆的high frequency heap,僅當應用程式解除安裝時,才釋放記憶體 | 單例類的單個例項是靜態的,因此也儲存在high frequency heap,當應用程式解除安裝時,才釋放記憶體。但是,與只能具有靜態物件的靜態類不同,單例類可以同時具有靜態和非靜態物件。因此,從記憶體管理的角度來看,當您使用單例類時,可以利用垃圾回收管理物件。 |
可擴充套件性 | 您不能繼承靜態類並覆蓋其方法 ;靜態類不能具有擴充套件方法 | 單例類通常包含一個私有建構函式,並標記為已密封,以指示它既不能例項化也不能繼承;因此,只有在單例類中具有非私有建構函式的情況下,才可以擴充套件單例類;單例類可以具有擴充套件方法 |
可測試性 | 模擬靜態類非常困難,特別是在包含靜態物件的時候。當然如果是隻有靜態方法,且冪等則還是很容易測試的 | 測試單例類很容易 |
3.使用場景
經過上面的對比,你應該看出端倪了。
當您只需要一個包含多個方法的工具類時,靜態類是一個不錯的選擇,在這種情況下您不需要例項。因為您沒有此類的任何例項,所以這個簡單的實現提高了應用程式的效能。
單例模式可用於設計只需要一個例項的類。典型示例包括用於日誌記錄,快取,執行緒池等的管理器類,在這些場景,單例類是一個不錯的選擇。為此,您應該有一個例項,以避免對同一資源的請求衝突。
還有在引入了DI框架後,你應該多多使用單例類,因為實現這樣的需求,就是簡單的定義一個普通的類,然後註冊到DI中即可。
當然還有一點就是單例類更加像面向物件程式設計,哈哈~~~
總結
到此這篇關於c#中單例類與靜態類的區別以及使用場景的文章就介紹到這了,更多相關c#單例類與靜態類的區別及使用內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!