俺们跟着来看拉姆(Lamb)da表达式在.NET中还有什么特殊的玩法,我们随后来看兰姆(Lamb)da表达式在.NET中还有如何特殊的玩法

图片 1

兰姆da表明式玩转多态

  Lambda怎样兑现多态?大家用抽象类和虚方法了,为啥还要用兰姆da那些家伙?且看下边的代码:

class MyBaseClass
{
    public Action SomeAction { get; protected set; }

    public MyBaseClass()
    {
        SomeAction = () =>
        {
            //Do something!
        };
    }
}

class MyInheritedClass : MyBaseClass
{
    public MyInheritedClass()
    {
        SomeAction = () => {
            //Do something different!
        };
    }
}

  我们的基类不是抽象类,也远非虚方法,不过把性能通过信托的主意表表露来,然后在子类中重新为大家的SomeAction赋予一个新的表明式。这就是大家贯彻多态的长河,当然父类中的SomeAction的set有protected的爱慕级别,不然就会被外表随易修改了。可是这还不全面,父类的SomeAction在子类中被覆盖将来,大家彻底访问不到它了,要精晓真实处境是大家得以经过base来访问父类原来的办法的。接下来就是实现那么些了:

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来兑现覆盖的同时,将本来的不二法门保存在previousActions中。这样大家就足以保障两岸同时存在了。

  我们明白子类是不可以掩盖父类的静态方法的,然则一旦我们想实现静态方法的掩盖呢?

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表达式作为性能,可以每天再一次赋值的特性。当然这只是一个简便的以身作则,真实项目中并不提出大家这么去做。 

  今天,我们跟着来看兰姆(Lamb)da表达式在.NET中还有哪些特殊的玩法。

图片 2

  上一篇 背后的故事之 –
快乐的Lambda表达式(一)
大家由浅入深的辨析了眨眼之间间Lambda表明式。知道了它和信托以及常见方法的界别,并且经过测试对照他们中间的性质,然后我们经过IL代码深入了然了拉姆(Lamb)da表明式,以及介绍了什么样在.NET中用Lambda表明式来落实JavaScript中大行其道的局部格局。

快乐的Lambda表达式

措施字典

  实际上那么些情势咱们在上一篇的回到方法中早就讲到了,只是没有如此一个名字而已,就终于一个总结吧。故事是这般的,你是不是平日会写到switch-case语句的时候觉得不够优雅?但是你又不想去整个什么工厂模式或者政策格局,那什么样让你的代码看起来高档一点呢?

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里面,这种协会章程其实是麻烦承受,大家来上学插件开发的法子,让它自己去找所有大家需要的点子。

static Dictionary<string, Action> finalizers;

// 在静态的构造函数用调用这个方法
public static void BuildFinalizers()
{
    finalizers = new Dictionary<string, Action>();

    // 获得当前运行程序集下所有的类型
    var types = Assembly.GetExecutingAssembly().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);
            }
        }
    }
} 

public Action GetFinalizer(string input)
{
    if(finalizers.ContainsKey(input))
        return finalizers[input];

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

  假如要兑现插件化的话,我们不仅要力所能及加载本程序集下的艺术,还要能随时甚至运转时去加载外部的格局,请继续往下看:

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);
            }
        }
    }
} 

  现在,我们就足以用这多少个点子,给它指定程序集去加载大家需要的东西了。

  最终留下我们一个题目,我们能写递归表明式么?下面的不二法门假如用表明式怎么着写吗?

int factorial(int n)
{
    if(n == 0)
        return 1;
    else
        return n * factorial(n - 1);
}

  

办法字典

  实际上那一个模式我们在上一篇的重临方法中早就讲到了,只是没有这样一个名字而已,就到底一个总计吧。故事是这么的,你是不是平时会写到switch-case语句的时候以为不够优雅?不过你又不想去整个什么工厂格局或者政策形式,这什么让您的代码看起来高档一点吧?

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里面,这种协会措施其实是麻烦接受,我们来学学插件开发的办法,让它和谐去找所有大家需要的主意。

static Dictionary<string, Action> finalizers;

// 在静态的构造函数用调用这个方法
public static void BuildFinalizers()
{
    finalizers = new Dictionary<string, Action>();

    // 获得当前运行程序集下所有的类型
    var types = Assembly.GetExecutingAssembly().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);
            }
        }
    }
} 

public Action GetFinalizer(string input)
{
    if(finalizers.ContainsKey(input))
        return finalizers[input];

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

  倘诺要实现插件化的话,我们不仅要力所能及加载本程序集下的艺术,还要能随时甚至运转时去加载外部的格局,请继续往下看:

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);
            }
        }
    }
} 

  现在,我们就足以用这些格局,给它指定程序集去加载大家需要的东西了。

  最后留给我们一个题材,大家能写递归表明式么?下边的不二法门假使用表达式如何写啊?

int factorial(int n)
{
    if(n == 0)
        return 1;
    else
        return n * factorial(n - 1);
}

  

兰姆(Lamb)da表明式玩转多态

  兰姆da如何落实多态?大家用抽象类和虚方法了,为什么还要用Lambda这么些东西?且看下边的代码:

class MyBaseClass
{
    public Action SomeAction { get; protected set; }

    public MyBaseClass()
    {
        SomeAction = () =>
        {
            //Do something!
        };
    }
}

class MyInheritedClass : MyBaseClass
{
    public MyInheritedClass()
    {
        SomeAction = () => {
            //Do something different!
        };
    }
}

  我们的基类不是抽象类,也平昔不虚方法,不过把性能通过信托的点子透透露来,然后在子类中再度为大家的SomeAction赋予一个新的表明式。这就是我们实现多态的经过,当然父类中的SomeAction的set有protected的保安级别,不然就会被表面随易修改了。不过这还不到家,父类的SomeAction在子类中被遮盖将来,我们彻底访问不到它了,要清楚真实情形是我们可以透过base来访问父类原来的办法的。接下来就是实现那个了:

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来实现覆盖的同时,将原本的不二法门保存在previousActions中。这样大家就足以保障双方同时存在了。

  我们知道子类是不可以遮住父类的静态方法的,然则假如我们想实现静态方法的覆盖呢?

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";
    }
}

  这里依然使用了将兰姆da表明式作为性能,可以每天再一次赋值的特性。当然这只是一个简单易行的演示,真实项目中并不指出我们这么去做。 

  前日,我们跟着来看Lambda表明式在.NET中还有咋样非凡的玩法。

快乐的Lambda表达式

  上一篇 幕后的故事之 –
快乐的兰姆(Lamb)da表达式(一)
大家由浅入深的分析了须臾间兰姆(Lamb)da表明式。知道了它和嘱托以及常见方法的分别,并且经过测试对照他们之间的性质,然后我们通过IL代码深远明白了Lambda表明式,以及介绍了怎么在.NET中用拉姆(Lamb)da表明式来落实JavaScript中大行其道的一些格局。

相关文章