C#基礎(chǔ) 延遲加載介紹與實(shí)例
延遲加載(lazy loading) 設(shè)計(jì)模式是為了避免一些無謂的性能開銷而提出來的,所謂延遲加載就是當(dāng)在真正需要數(shù)據(jù)(讀取屬性值)的時(shí)候,才真正執(zhí)行數(shù)據(jù)加載操作.
為了便于理解, 我們來建立一個(gè)場景, 假設(shè)我們要構(gòu)造一個(gè)Hero(英雄) 類, 每個(gè)Hero 有自己的名字和(SpecialSkill)特殊技能.
建模
這是一種建立的方法:
public class Hero
{
public string FullName { get; set; }
public string Name { get; set; }
public SpecialSkill Skill{ get; set; }
public Hero(string name)
{
Name = name;
FullName = "Super " + name;
Skill = new SpecialSkill(name);
}
}
public class SpecialSkill
{
public int Power { get; set; }
public string SkillName { get; set; }
public int StrengthSpent { get; set; }
public SpecialSkill(string name)
{
Console.WriteLine("loading special skill .....");
Power = name.Length;
StrengthSpent = name.Length * 3;
SkillName = name + " Blazing";
Console.WriteLine(SkillName + ",... this's what makes a legend!");
}
}
class Program
{
static void Main(string[] args)
{
Hero hero = new Hero("wukong");
Console.WriteLine("\n\n.......................Press Enter to continue.......................\n\n");
Console.Read();
Console.WriteLine("Hero's special skill: " + hero.Skill.SkillName);
Console.Read();
Console.Read();
}
}
運(yùn)行程序后輸出如下, 這個(gè)例子非常的容易理解, 結(jié)果也是顯然的.
它的缺點(diǎn)是, 當(dāng)運(yùn)行Hero 構(gòu)造函數(shù)的時(shí)候, SpecialSkill 的所有屬性都已經(jīng)加載了. 如果我們只想獲取這個(gè)Hero 的FullName, 我們也加載了SpecialSkill 所有值.
屬性的加載延遲
在沒有Lazy<T> 以前我們可以這樣做:
public class Hero
{
public string FullName { get; set; }
public string Name { get; set; }
private SpecialSkill skill;
public SpecialSkill Skill
{
get { return skill ?? (skill = new SpecialSkill(Name)); }
}
public Hero(string name)
{
Name = name;
FullName = "Super " + name;
}
}
即: 修改屬性SpecialSkill的加載方法. 那么當(dāng)我們再運(yùn)行程序時(shí), 得到的輸出就是:
非常好! 這就是我們要的效果, 這樣可以讓系統(tǒng)更加的有效率.
Lazy<T>
當(dāng)net framework 引入了Lazy<T> 類后, 我們也可以使用它來實(shí)現(xiàn):
public class Hero
{
public string FullName { get; set; }
public string Name { get; set; }
private readonly Lazy<SpecialSkill> skill;
public SpecialSkill Skill
{
get { return skill.Value; }
}
public Hero(string name)
{
Name = name;
FullName = "Super " + name;
skill = new Lazy<SpecialSkill>(() => new SpecialSkill(name));
}
}
Lazy<T>提供對(duì)延遲初始化的支持。而 Lazy<T> 中的一個(gè)屬性 Value, 則是獲取當(dāng)前 Lazy<T> 實(shí)例的延遲初始化值。
Lazy<T>的優(yōu)勢
那么既然我們已經(jīng)可以用屬性緩存的方法實(shí)現(xiàn), 為什么還要引入Lazy<T> ?
至少Lazy<T> 有以下幾點(diǎn)優(yōu)勢:
它具有 LazyThreadSafetyMode, 但是我們一般不使用它, 除非是很關(guān)鍵的情況下(在此略去181個(gè)字)
它使屬性的定義行更加簡單
從語義上來講, 它更加明確, 更加具有可讀性
它允許null為有效值
相關(guān)文章
C#版的 Escape() 和 Unescape() 函數(shù)分享
從網(wǎng)上看到兩個(gè)方法, C# 版的 Escape() 和 Unescape(),收藏下。2011-05-05C#實(shí)現(xiàn)簡單的Login窗口實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)簡單的Login窗口,實(shí)例分析了C#顯示及關(guān)閉登陸Login窗口的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-08-08C#打包部署并把.net framework框架打到安裝包的方法步驟
打包c(diǎn)#程序時(shí),有時(shí)需要添加.net framework組件到安裝包,本文就來介紹一下C#打包部署并把.net framework框架打到安裝包的方法步驟,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10C#中IEnumerable、ICollection、IList、List之間的區(qū)別
這篇文章主要介紹了C#中IEnumerable、ICollection、IList、List之間的區(qū)別,本文分別分析了它的實(shí)現(xiàn)源碼,從而總結(jié)出了它們之間的關(guān)系和不同之處,需要的朋友可以參考下2015-06-06C#中使用1.7版本驅(qū)動(dòng)操作MongoDB簡單例子
這篇文章主要介紹了C#中使用1.7版本驅(qū)動(dòng)操作MongoDB簡單例子,本文給出了連接MongoDB、操作MongoDB數(shù)據(jù)等例子,需要的朋友可以參考下2015-01-01C#使用System.Buffer以字節(jié)數(shù)組Byte[]操作基元類型數(shù)據(jù)
這篇文章介紹了C#使用System.Buffer以字節(jié)數(shù)組Byte[]操作基元類型數(shù)據(jù)的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05基于C#動(dòng)手實(shí)現(xiàn)網(wǎng)絡(luò)服務(wù)器Web Server
這篇文章主要為大家詳細(xì)介紹了基于C#動(dòng)手實(shí)現(xiàn)網(wǎng)絡(luò)服務(wù)器Web Server,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10C#利用System.Threading.Thread.Sleep即時(shí)輸出信息的詳解
本篇文章是對(duì)C#利用System.Threading.Thread.Sleep即時(shí)輸出信息進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06WPF/Silverlight實(shí)現(xiàn)圖片局部放大的方法分析
這篇文章主要介紹了WPF/Silverlight實(shí)現(xiàn)圖片局部放大的方法,結(jié)合實(shí)例形式分析了WPF/Silverlight針對(duì)圖片屬性操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-03-03