如何使用 C# 中的 Lazy
延遲初始化
是一種將物件的建立延遲到第一次需要用時的技術,換句話說,物件的初始化是發生在真正需要的時候才執行,值得注意的是,術語 延遲初始化
和 延遲例項化
的意思是相同的——可以互換使用,透過使用 延遲初始化
技術,可以避免應用程式不必要的計算和記憶體消耗,這篇文章我們將會討論如何在 C# 中使用 延遲初始化。
有些朋友聽完這些可能會懵逼,接下來用一個簡單的例子來了解下 延遲載入
的場景,考慮下面兩個類, Customer
和 Order
, Customer 類包含了一個 Orders 屬性,一個人肯定會有很多的訂單,也就意味著它可能包含了很多的資料,甚至還需要連線資料庫去獲取 Orders 記錄,在這種場景下,沒必要給 customer 集合中的所有人都帶上完整的 orders,這個初始化開銷是巨大的,最佳化點就是不載入 Orders,直到某些 customer 真的需要 Orders 時才按需灌入。
使用 Lazy
你可以自己寫一段邏輯來實現 延遲初始化
,在 .Net Framework 4.0
之後就沒必要了, 因為在 System
名稱空間下已經提供了 Lazy
,而且還是 執行緒安全
的,可以使用這個類來延遲 資源密集型 的物件按需建立。
當使用 Lazy
的時候,這裡的 T 就是你要延遲的集合,那如何做到按需載入呢?呼叫 Lazy.Value
即可,下面的程式碼片段展示瞭如何使用 Lazy
。
Lazy> orders = new Lazy>();
IEnumerable result = lazyOrders.Value;
現在,考慮下面的兩個類: Author
和 Blog
,一個作者可以寫很多文章,所以這兩個類之間是 一對多
的關係,下面的程式碼片段展示了這種關係。
public class Author
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public List Blogs { get; set; }
}
public class Blog
{
public int Id { get; set; }
public string Title { get; set; }
public DateTime PublicationDate { get; set; }
}
值得注意的是,關係型資料庫中的 一對多
關係對映到物件模型就是 Author
類中增加一個 List Blogs 屬性,使用這個屬性,Author 就可以維持一個或者多個 Blog 例項物件,對吧。
現在假定在 使用者介面
上僅需展示 Author 的基礎資訊,比如說:(firstname,lastname,address),在這種場景下,給 Author 物件載入 Blogs 集合是毫無意義的,當真的需要載入 Blogs 時,執行 Blogs.Value 即可立即執行,下面展示了 Lazy Blogs
的用法。
public class Author
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public Lazy> Blogs => new Lazy>(() => GetBlogDetailsForAuthor(this.Id));
private IList GetBlogDetailsForAuthor(int Id)
{
//Write code here to retrieve all blog details for an author.
}
}
使用通用的 Lazy
接下來讓我們看看如何使用泛型的 Lazy
實現單例模式,下面的 StateManager
是執行緒安全的,同時為了演示 延遲初始化
,我使用了 靜態建構函式 來確保 C# 編譯器不會將它標記為 beforefieldinit
。
public sealed class StateManager
{
private StateManager()
{
}
public static StateManager Instance
{
get
{
return Nested.obj;
}
}
private class Nested
{
static Nested()
{
}
internal static readonly StateManager obj = new StateManager();
}
}
下面我用 Lazy
來包裝 StateManager,你會發現使用 Lazy
來做延遲初始化真的是太簡單了。。。
public class StateManager
{
private static readonly Lazy obj = new Lazy(() => new StateManager());
private StateManager() { }
public static StateManager Instance
{
get
{
return obj.Value;
}
}
}
可以瞄一下上面程式碼的 Instance 屬性,它被做成只讀屬性了,同時也要注意 obj.Value
也是一個只讀屬性。
public class Lazy
{
public T Value
{
get
{
if (_state != null)
{
return CreateValue();
}
return _value;
}
}
}
延遲初始化 是一個很不錯的效能最佳化技術,它允許你將那些 資源密集型 的物件延遲到你真正需要載入的時候再載入,大家結合自己的場景盡情的使用吧!
更多高質量乾貨:參見我的 GitHub: [csharptranslate] github.com/ctripxchuang/csharptranslate
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2894/viewspace-2826894/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 如何使用 C# 中的 ValueTaskC#
- Vue中computed的本質—lazy WatchVue
- C#中普通快取的使用C#快取
- Lazy Load
- 如何在C#中使用MSMQC#MQ
- 如何在 C# 中使用 ChannelsC#
- C#中的char和string的使用簡介C#
- 【swagger】C# 中 swagger 的使用及避坑SwaggerC#
- Lazy安裝
- spring的延遲初始化bean (default-lazy-init 與 lazy-init )SpringBean
- SAP Fiori裡的List是如何做到懶載入Lazy load的
- C#/Vsto中CustomTaskPanes和Ribbon的使用方法C#
- [C#]C#中字串的操作C#字串
- 使用C#如何監控選定資料夾中檔案的變動情況?C#
- 如何在C#專案中使用NHibernateC#
- 來看看如何在 C# 中使用反射C#反射
- C# ExpandoObject的使用C#Object
- C# RabbitMQ的使用C#MQ
- async/await 在 C# 語言中是如何工作的?(中)AIC#
- C# 中的“智慧列舉”:如何在列舉中增加行為C#
- C#中的MVCC#MVC
- C#中的MVVMC#MVVM
- c#中的事件C#事件
- C#中的集合C#
- [譯] lazy var in ios swiftiOSSwift
- v2 img lazy
- [Vue Router] Lazy loading routesVue
- C# 9.0中引入的新特性init和record的使用思考C#
- 如何在C#中使用Google.Protobuf工具C#Go
- 如何使用python中的opengl?Python
- Flask-sqlalchemy中 backref lazy的引數例項解釋和選擇FlaskSQL
- C#分散式專案中是否使用MassTransitC#分散式
- 如何在C#中除錯LINQ查詢C#除錯
- c#中lock的使用(用於預約超出限額的流程)C#
- C#中Enum的用法C#
- 理解C#中的ValueTaskC#
- 理解C#中的ConfigureAwaitC#AI
- C# 中的特性 AttributeC#