本日,我们接着来看Lambda表达式在.NET中另有哪些新颖的弄法。
Lambda表达式玩转多态
Lambda怎样完成多态?我们用抽象类和虚要领了,为何还要用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"; } }
这里照样利用了将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); }
以上就是背地的故事之 - 快活的Lambda表达式(二)的内容,更多相关内容请关注ki4网(www.ki4.cn)!