.NET 4.0 引入 System.Lazy<T> 類,提供線程安全的延遲初始化封裝,避免不必要的對象創建開銷,提升啟動性能與內存利用率。本文詳解其構造方式、核心屬性、實戰示例及適用場景。
Lazy<T> 封裝一個值工廠委托,僅在首次訪問 Value 屬性時執行初始化,後續訪問直接返回緩存結果。支持多線程安全初始化(默認模式)。
// 構造:傳入無參、返回 T 的委托(Lambda/靜態方法/實例方法均可)
Lazy<string> lazyString = new Lazy<string>(TestLazy.GetString);
// 判斷是否已初始化
Console.WriteLine(lazyString.IsValueCreated); // False
// 首次訪問 Value 觸發初始化
Console.WriteLine(lazyString.Value); // 輸出當前時間字符串
// 再次訪問直接返回緩存值
Console.WriteLine(lazyString.IsValueCreated); // True
靜態工廠方法示例:
public class TestLazy
{
public static string GetString()
{
return DateTime.Now.ToLongTimeString();
}
}
博客用戶包含多篇文章,加載用戶時不預加載文章,僅在訪問 Articles 時查詢:
public class BlogUser
{
public int Id { get; private set; }
// Lazy 包裝 List<Article>,工廠委托捕獲外部 id
public Lazy<List<Article>> Articles { get; private set; }
public BlogUser(int id)
{
this.Id = id;
Articles = new Lazy<List<Article>>(() => ArticleServices.GetArticlesByUserId(id));
Console.WriteLine("BlogUser Initializer");
}
}
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public DateTime PublishDate { get; set; }
}
public static class ArticleServices
{
public static List<Article> GetArticlesByUserId(int userId)
{
Console.WriteLine("Article Initializer - 此時才查詢數據庫");
return new List<Article> {
new Article { Id = 1, Title = "Lazy Load", PublishDate = DateTime.Parse("2011-4-20") },
new Article { Id = 2, Title = "Delegate", PublishDate = DateTime.Parse("2011-4-21") },
// ...
};
}
}
// 使用
var blogUser = new BlogUser(1);
Console.WriteLine("blogUser has been initialized"); // 未觸發 Articles 初始化
foreach (var article in blogUser.Articles.Value) // 此處觸發查詢
{
Console.WriteLine(article.Title);
}
BlogUser Initializer
blogUser has been initialized
Article Initializer - 此時才查詢數據庫
Lazy Load
Delegate
...
| 屬性/構造參數 | 說明 |
|---|---|
Value | 獲取實例,首次訪問觸發初始化,後續返回緩存。 |
IsValueCreated | 只讀,指示是否已完成初始化。 |
LazyThreadSafetyMode | 構造函數可指定: ExecutionAndPublication(默認,全鎖雙檢查,線程安全); PublicationOnly(允許並發初始化,取首個完成結果); None(不保證線程安全,性能最好)。 |
Lazy<T>,主線程快速啟動,背景按需初始化。private static readonly Lazy<MyService> _instance = new Lazy<MyService>(() => new MyService()); 替代雙重檢查鎖。Value 時拋出,後續訪問不會重試(除非使用 PublicationOnly 模式)。Lazy<T> 實例。Lazy<T> 是 .NET 基礎類庫中極具實用價值的類型,善用它能讓資源分配更精準、啟動更迅捷、代碼意圖更清晰。