午夜国产狂喷潮在线观看|国产AⅤ精品一区二区久久|中文字幕AV中文字幕|国产看片高清在线

    背后的故事之 - 快樂的Lambda表達式(二)
    來源:易賢網(wǎng) 閱讀:1244 次 日期:2015-04-02 12:15:50
    溫馨提示:易賢網(wǎng)小編為您整理了“背后的故事之 - 快樂的Lambda表達式(二)”,方便廣大網(wǎng)友查閱!

    名單

    上一篇 背后的故事之 – 快樂的Lambda表達式(一)我們由淺入深的分析了一下Lambda表達式。知道了它和委托以及普通方法的區(qū)別,并且通過測試對比他們之間的性能,然后我們通過IL代碼深入了解了Lambda表達式,以及介紹了如何在.NET中用Lambda表達式來實現(xiàn)JavaScript中流行的一些模式。

    今天,我們接著來看Lambda表達式在.NET中還有哪些新鮮的玩法。

    Lambda表達式玩轉多態(tài)

    Lambda如何實現(xiàn)多態(tài)?我們用抽象類和虛方法了,為什么還要用Lambda這個玩意?且看下面的代碼:

    class MyBaseClass

    {

    public Action SomeAction { get; protected set; }

    public MyBaseClass()

    {

    SomeAction = () =>

    {

    //Do something!

    };

    }

    }

    class MyInheritedClass : MyBaseClass

    {

    public MyInheritedClass()

    {

    SomeAction = () => {

    //Do something different!

    };

    }

    }

    我們的基類不是抽象類,也沒有虛方法,但是把屬性通過委托的方式暴露出來,然后在子類中重新為我們的SomeAction賦予一個新的表達式。這就是我們實現(xiàn)多態(tài)的過程,當然父類中的SomeAction的set有protected的保護級別,不然就會被外部隨易修改了。但是這還不完美,父類的SomeAction在子類中被覆蓋之后,我們徹底訪問不到它了,要知道真實情況是我們可以通過base來訪問父類原來的方法的。接下來就是實現(xiàn)這個了

    class MyBaseClass

    {

    public Action SomeAction { get; private set; }

    Stack<Action> previousActions;

    protected void AddSomeAction(Action newMethod)

    {

    previousActions.Push(SomeAction);

    SomeAction = newMethod;

    }

    protected void RemoveSomeAction()

    {

    if(previousActions.Count == 0)

    return;

    SomeAction = previousActions.Pop();

    }

    public MyBaseClass()

    {

    previousActions = new Stack<Action>();

    SomeAction = () => {

    //Do something!

    };

    }

    }

    上面的代碼中,我們通過AddSomeAction來實現(xiàn)覆蓋的同時,將原來的方法保存在previousActions中。這樣我們就可以保持兩者同時存在了。

    大家知道子類是不能覆蓋父類的靜態(tài)方法的,但是假設我們想實現(xiàn)靜態(tài)方法的覆蓋呢?

    void Main()

    {

    var mother = HotDaughter.Activator().Message;

    //mother = "I am the mother"

    var create = new HotDaughter();

    var daughter = HotDaughter.Activator().Message;

    //daughter = "I am the daughter"

    }

    class CoolMother

    {

    public static Func<CoolMother> Activator { get; protected set; }

    //We are only doing this to avoid NULL references!

    static CoolMother()

    {

    Activator = () => new CoolMother();

    }

    public CoolMother()

    {

    //Message of every mother

    Message = "I am the mother";

    }

    public string Message { get; protected set; }

    }

    class HotDaughter : CoolMother

    {

    public HotDaughter()

    {

    //Once this constructor has been "touched" we set the Activator ...

    Activator = () => new HotDaughter();

    //Message of every daughter

    Message = "I am the daughter";

    }

    }

    這里還是利用了將Lambda表達式作為屬性,可以隨時重新賦值的特點。當然這只是一個簡單的示例,真實項目中并不建議大家這么去做。

    方法字典

    實際上這個模式我們在上一篇的返回方法中已經(jīng)講到了,只是沒有這樣一個名字而已,就算是一個總結吧。故事是這樣的,你是不是經(jīng)常會寫到switch-case語句的時候覺得不夠優(yōu)雅?但是你又不想去整個什么工廠模式或者策略模式,那怎么樣讓你的代碼看起來高級一點呢?

    public Action GetFinalizer(string input)

    {

    switch

    {

    case "random":

    return () => { /* ... */ };

    case "dynamic":

    return () => { /* ... */ };

    default:

    return () => { /* ... */ };

    }

    }

    //-------------------變身之后-----------------------

    Dictionary<string, Action> finalizers;

    public void BuildFinalizers()

    {

    finalizers = new Dictionary<string, Action>();

    finalizers.Add("random", () => { /* ... */ });

    finalizers.Add("dynamic", () => { /* ... */ });

    }

    public Action GetFinalizer(string input)

    {

    if(finalizers.ContainsKey(input))

    return finalizers[input];

    return () => { /* ... */ };

    }

    好像看起來是不一樣了,有那么一點味道。但是一想是所有的方法都要放到那個BuildFinalizers里面,這種組織方法實在是難以接受,我們來學學插件開發(fā)的方式,讓它自己去找所有我們需要的方法。

    static Dictionary<string, Action> finalizers;

    // 在靜態(tài)的構造函數(shù)用調用這個方法

    public static void BuildFinalizers()

    {

    finalizers = new Dictionary<string, Action>();

    // 獲得當前運行程序集下所有的類型

    var types = Assembly.GetExecutingAssembly().GetTypes();

    foreach(var type in types)

    {

    // 檢查類型,我們可以提前定義接口或抽象類

    if(type.IsSubclassOf(typeof(MyMotherClass)))

    {

    // 獲得默認無參構造函數(shù)

    var m = type.GetConstructor(Type.EmptyTypes);

    // 調用這個默認的無參構造函數(shù)

    if(m != null)

    {

    var instance = m.Invoke(null) as MyMotherClass;

    var name = type.Name.Remove("Mother");

    var method = instance.MyMethod;

    finalizers.Add(name, method);

    }

    }

    }

    }

    public Action GetFinalizer(string input)

    {

    if(finalizers.ContainsKey(input))

    return finalizers[input];

    return () => { /* ... */ };

    }

    如果要實現(xiàn)插件化的話,我們不光要能夠加載本程序集下的方法,還要能隨時甚至運行時去加載外部的方法,請繼續(xù)往下看:

    internal static void BuildInitialFinalizers()

    {

    finalizers = new Dictionary<string, Action>();

    LoadPlugin(Assembly.GetExecutingAssembly());

    }

    public static void LoadPlugin(Assembly assembly)

    {

    var types = assembly.GetTypes();

    foreach(var type in types)

    {

    if(type.IsSubclassOf(typeof(MyMotherClass)))

    {

    var m = type.GetConstructor(Type.EmptyTypes);

    if(m != null)

    {

    var instance = m.Invoke(null) as MyMotherClass;

    var name = type.Name.Remove("Mother");

    var method = instance.MyMethod;

    finalizers.Add(name, method);

    }

    }

    }

    }

    現(xiàn)在,我們就可以用這個方法,給它指定程序集去加載我們需要的東西了。

    最后留給大家一個問題,我們能寫遞歸表達式么?下面的方法如果用表達式如何寫呢?

    int factorial(int n)

    {

    if(n == 0)

    return 1;

    else

    return n * factorial(n - 1);

    }

    更多信息請查看IT技術專欄

    更多信息請查看技術文章
    易賢網(wǎng)手機網(wǎng)站地址:背后的故事之 - 快樂的Lambda表達式(二)

    2025國考·省考課程試聽報名

    • 報班類型
    • 姓名
    • 手機號
    • 驗證碼
    關于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點 | 投訴建議
    工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務許可證:(云)人服證字(2023)第0102001523號
    聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關注公眾號:hfpxwx
    咨詢QQ:1093837350(9:00—18:00)版權所有:易賢網(wǎng)