2010年8月20日 星期五

System.Lazy 介紹 - .NET Framework 4 c# 新功能

System.Lazy為.NET Framework 4 c#新增的功能,主要可讓我們在程式中延遲產生執行個體(instance)。有些應用中,我們並不需要在宣告的時候就真的產生一個執行個體,可在真的要用到時,再透過執行與取得Lazy類別的屬性Value實際去產生一個執行個體,這樣可用再需節省寶貴的系統資源上,如須事先大量反覆且複雜運算或是存取資料庫的時候。


擷自網站: www.space.com NASA 最新機器太空人Robonauts2


一個範例


假設有一個Robot(機器人)類別,該機器人有兩個主要功用:

1.整理花園(Garden Assistant):不需耗費大量機器人資源。
2.建造房屋(Building Creater):需耗費大量機器人資源且須投入現金方可建造房屋完成。


我們先建立「花園」與「房屋」的類別如下:



public class Garden
{
    private string _msg = "Robot build a garden!";
    public string Create()
    {
        return _msg;
    }
}


public class House
{
    private string _msg = "Robot build a house!";
    public House(int cost)
    {
        _msg += " It's cost is NT$" + cost;
    }
 
    public string Create()
    {
        return _msg;
    }
}


實作將System.Lazy封裝到類別中


接著我們也建立Robot類別,這個類別可透過呼叫Create()這個方法來完成「整理花園」或是「建造房屋」這兩項機器人所提供的功用。並且可傳遞一個檢驗訊號(Msg這個屬性),這個檢驗訊號用來判斷目前使用Lazy類別的instance是否已經被建立了。


public class Robot
{
    private Lazy<House> _house;
    private Garden _garden;
    private string _msg;
 
    public Robot()
    {
        _house = new Lazy<House>(() => new House(99000));
        _garden = new Garden();
    }
 
    public Garden CleanGarden
    {
        get { return _garden; }
    }
 
    public House BuildHouse
    {
        get { return _house.Value; }//這裡才真的建立instance
    }
 
    public string Msg
    {
        get
        {
            if (_house.IsValueCreated)
                _msg = "The instance of house"
                +"has been created!";
            else
                _msg = "The instance of house"
                +"not be created!";
                return _msg;
        }
    }
}


我們建立Robot類別的執行個體時(instance)時,因為尚不需要機器人實際去「建造房屋」,因為「建造房屋」所費不貲,請須耗費機器人大量的時間與資源,也可能減損機器人的壽命,所以我們為「建造房屋」加上Lazy的類別,一直等到我們實際要「建造房屋」,就去執行Lazy類別中的屬性Value,系統會真正將Lazy這個instance建立起來,然後我們可以利用此instance去呼叫「房屋」類別的的Create()這個方法來建立房屋。


我們也可以帶入「建屋成本」這項整數型態的參數到房屋類別中,如上述程式的$99,000。而「整理花園」這建機器人的工作,就不需耗費機器人大量的時間與資源,故我們直接使用一般建立執行個體(instance)的方式來(new SomeClass())讓機器人可完成「整理花園」這項輕鬆的工作。


執行結果


前端介面如下兩個圖示,使用者按下按鈕下達命令要機器人去「整理花園」或「建造房屋」,然後並且顯示出一段機器人執行狀況(藍字),與顯示出檢驗訊號字串(紅字)。

按下「整理花園」按鈕時的顯示畫面,由紅色檢驗訊號字串可看出我們雖然已經使用了new Lazy<House>這對程式建立了house,但系統尚未真的建立instance。



按下「建造房屋」按鈕時的顯示畫面,由紅色檢驗訊號字串可看出此時系統真的去建立instance,並用此instance來執行「建造房屋」。



當然我們可以使用自行定義的類別與其中的方法也可以達到延遲產生執行個體(instance)的功能,但微軟在.NET Framework 4中推出System.Lazy,就是希望開發者可以直接使用,優點是有一致的意外處理(Exception)介面可使用,且符合執行緒的安全性考量。


相關聯結


Lazy<T> 類別-MSDN

http://msdn.microsoft.com/zh-tw/library/dd642331.aspx

延遲初始設定-MSDN

http://msdn.microsoft.com/zh-tw/library/dd997286.aspx

HOW TO:執行物件的延遲初始化-MSDN

http://msdn.microsoft.com/zh-tw/library/dd460709.aspx

LazyList<T> vs System.Lazy<List<T>> in ASP.NET MVC 2 stackoverflow

http://stackoverflow.com/questions/2689986/lazylistt-vs-system-lazylistt-in-asp-net-mvc-2

Lazy initialization in .NET 4 – Lazy<T>

http://reedcopsey.com/2009/10/26/lazy-initialization-in-net-4-lazyt/

Getting Lazy with System.Lazy

http://devlicio.us/blogs/derik_whittaker/archive/2010/05/19/getting-lazy-with-system-lazy.aspx

沒有留言:

張貼留言