lambda应用设计模式

上传人:第*** 文档编号:32687630 上传时间:2018-02-12 格式:DOC 页数:19 大小:76.50KB
返回 下载 相关 举报
lambda应用设计模式_第1页
第1页 / 共19页
lambda应用设计模式_第2页
第2页 / 共19页
lambda应用设计模式_第3页
第3页 / 共19页
lambda应用设计模式_第4页
第4页 / 共19页
lambda应用设计模式_第5页
第5页 / 共19页
点击查看更多>>
资源描述

《lambda应用设计模式》由会员分享,可在线阅读,更多相关《lambda应用设计模式(19页珍藏版)》请在金锄头文库上搜索。

1、Lambda 应用设计模式在使用 Lambda 表达式时,我们常会碰到一些典型的应用场景,而从常用场景中抽取出来的应用方式可以描述为应用模式。这些模式可能不全是新的模式,有的参考自 JavaScript 的设计模式,但至少我看到了一些人为它们打上了名字标签。无论名字的好与坏,我还是决定给这些模式进行命名,至少这些名字很具有描述性。同时我也会给出这些模式的可用性、强大的部分和危险的部分。提前先说明:绝大多数模式是非常强大的,但有可能在代码中引入些潜在的 Bug。所以,慎用。老生常谈了。事实上,在 .NET 的第一个版本中就已经支持回调模式了,但形式有所不同。现在通过 Lambda 表达式中的闭包

2、和局部变量捕获,这个功能变得越来越有趣了。现在我们的代码可以类似于:复制代码1 void CreateTextBox()2 3 var tb = new TextBox();4 tb.IsReadOnly = true;5 tb.Text = Please wait .;6 DoSomeStuff() =7 8 tb.Text = string.Empty;9 tb.IsReadOnly = false;10 );11 12 13 void DoSomeStuff(Action callback)14 15 / Do some stuff - asynchronous would be hel

3、pful .16 callback();17 复制代码对于 JavaScript 开发人员,这个模式已经没什么新鲜的了。而且通常我们在大量的使用这种模式,因为其非常的有用。例如我们可以使用时间处理器作为参数来处理 AJAX 相关的事件等。在 LINQ 中,我们也使用了这个模式,例如 LINQ 中的 Where 会在每次迭代中回调查询函数。这些仅是些能够说明回调模式非常有用的简单的示例。在 .NET 中,通常推荐使用事件回调机制。原因有两点,一是已经提供了特殊的关键字和类型模式(有两个参数,一个是发送者,一个数事件参数,而发送者通常是 object 类型,而事件参数通常从 EventArgs 继

4、承) ,同时通过使用 += 和 -+ 操作符,也提供了调用多个方法的机会。函数作为返回值 (Returning Functions)就像常见的函数一样,Lambda 表达式可以返回一个函数指针(委托实例) 。这就意味着我们能够使用一个 Lambda 表达式来创建并返回另一个 Lambda 表达式。这种行为在很多场景下都是非常有用的。我们先来看下面这个例子:复制代码 1 Func SayMyName(string language)2 3 switch (language.ToLower()4 5 case fr:6 return name =7 8 return Je mappelle + n

5、ame + .;9 ;10 case de:11 return name =12 13 return Mein Name ist + name + .;14 ;15 default:16 return name =17 18 return My name is + name + .;19 ;20 21 22 23 void Main()24 25 var lang = de;26 /Get language - e.g. by current OS settings27 var smn = SayMyName(lang);28 var name = Console.ReadLine();29

6、var sentence = smn(name);30 Console.WriteLine(sentence);31 复制代码这段代码可以写的更简洁些。如果请求的语言类型未找到,我们可以直接抛出一个异常,以此来避免返回一个默认值。当然,出于演示的目的,这个例子展示了类似于一种函数工厂。另外一种方式是引入 Hashtable ,或者更好的 Dictionary 类型。复制代码1 static class Translations2 3 static readonly Dictionary smnFunctions 4 = new Dictionary();5 6 static Translati

7、ons()7 8 smnFunctions.Add(fr, name = Je mappelle + name + .);9 smnFunctions.Add(de, name = Mein Name ist + name + .);10 smnFunctions.Add(en, name = My name is + name + .);11 12 13 public static Func GetSayMyName(string language)14 15 /Check if the language is available has been omitted on purpose16

8、return smnFunctionslanguage;17 18 19 20 / Now it is sufficient to call Translations.GetSayMyName(de) 21 / to get the function with the German translation.复制代码尽管这看起来有点过度设计之嫌,但毕竟这种方式很容易扩展,并且可以应用到很多场景下。如果结合反射一起使用,可以使程序变得更灵活,易于维护,并且更健壮。下面展示了这个模式如何工作:自定义函数 (Self-Defining Functions)在 JavaScript 中,自定义函数是一种

9、极其常见的设计技巧,并且在某些代码中可以获得更好的性能。这个模式的主要思想就是,将一个函数作为一个属性,而此属性可以被其他函数很容易的更改。复制代码1 class SomeClass2 3 public Func NextPrime4 5 get;6 private set;7 8 9 int prime;10 11 public SomeClass()12 13 NextPrime = () =14 15 prime = 2;16 17 NextPrime = () =18 19 /Algorithm to determine next - starting at prime20 /Set

10、prime21 return prime;22 ;23 24 return prime;25 ;26 27 复制代码在这里做了什么呢?首先我们得到了第一个质数,值为 2。这不是重点,重点在于我们可以调整算法来排除所有偶数。这在一定程度上会加快我们的算法,但我们仍然设置 2 为质数的起点。我们无需看到是否已经调用了 NextPrime() 函数,因为根据函数内的定义会直接返回 2。通过这种方式,我们节省了资源,并且能够优化算法。同样,我们也看到了这么做可以性能会更好。让我们来看下下面这个例子:复制代码1 Action loopBody = i = 2 if(i = 1000)3 loopBody

11、 = /* set to the body for the rest of the operations */;4 5 /* body for the first 1000 iterations */6 ;7 8 for(int j = 0; j 2 / Do Something here!3 )();代码看起来很简单。如果我们需要传递一些参数,则需要指定参数的类型。1 (string s, int no) = 2 / Do Something here!3 )(Example, 8);看起来写了这么多行代码并没有给我们带来什么好处。尽管如此,我们可以将这个模式和 async 关键字结合使用。

12、1 await (async (string s, int no) = 2 / Do Something here async using Tasks!3 )(Example, 8);4 5 /Continue here after the task has been finished这样,类似于异步包装器的用法就形成了。对象即时初始化 (Immediate Object Initialization)将这个模式包含在这篇文章当中的原因是,匿名对象这个功能太强大了,而且其不仅能包含简单的类型,而且还能包含 Lambda 表达式。复制代码1 /Create anonymous object2 v

13、ar person = new3 4 Name = Florian,5 Age = 28,6 Ask = (string question) =7 8 Console.WriteLine(The answer to + question + is certainly 42!);9 10 ;11 12 /Execute function13 person.Ask(Why are you doing this?);复制代码如果你运行了上面这段代码,可能你会看到一个异常(至少我看到了) 。原因是,Lambda 表达式不能被直接赋予匿名对象。如果你觉得不可思议,那我们的感觉就一样了。幸运的是,编译器告诉了我们“老兄,我不知道我应该为这个 Lambda 表达式创建什么样的委托类型” 。既然这样,我们就帮下编译器。复制代码1 var person = new2 3 Name = Florian,4 Age = 28,5 Ask = (Action)(string question) =6 7

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 中学教育 > 职业教育

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号