每周源代码19 – LINQ,多些What,少些How


[原文发表地址] The Weekly Source Code 19 - LINQ and More What, Less How
[原文发表时间] 2008-03-13 11:00

亲爱的读者,这里为您奉上第十九篇《每周源代码》,此后该系列文章还将源源不断地为您呈现。

在微软互联网体验大会(MIX: Microsoft Internet eXperience)上,Clint Rutkas和我一起给他的一个应用程序写了一个插件模型。我们做原型开发的时候,我敲出下面典型的插件风格代码:

   1: string[] filesToTest = Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins"), "*.dll");
   2: foreach (string file in filesToTest)
   3: {
   4:     Assembly a = Assembly.LoadFrom(file);
   5:     foreach (Type t in a.GetTypes())
   6:     {
   7:         if (!t.IsAbstract && t.BaseType == typeof(MyBaseClass))
   8:         {
   9:             myListOfInstances.Add((MyBaseClass)Activator.CreateInstance(t, credentials));
  10:         }
  11:     }
  12: }

这非常简单,几乎没有什么错误要处理。它通过遍历/plugins文件夹中的DLL并一一加载(这相对于一揽子加载文件夹中所有的dll要更明确),然后查找任意继承于MyBaseClass的非抽象类,将他们实例化并加入到一个列表中。

我想在这篇以及下一篇文章中引用Jeff Moser一篇很棒的博文《怎样才能成为特级大师》。我建议大家现在就去拜读一下,我等你们回来。

Jeff引用了Anders Heilsberg(C#和LINQ之父)的一段话:

“按照Ander最新的说法——C#未来的版本将让程序员们从如何完成一个结果中宣称‘多一些what,少一些how。这个说法的影响就是你的‘大块头’在运行时会更加有效,更重要的是,你的大脑也会更加有效。

我要重申我加粗的部分,我喜欢那些能让我宣称“多些what,少些How”的编程语言。这让我们在我上一份工作中努力设计一个系统时,不自觉地倾向于那些支持这种想法的系统。

回到上面的foreach循环,当我和Clint在工作的时候,我的好朋友Kzu来了,他建议我们把这个越显复杂的代码加工成一个LINQ查询。

经过几轮尝试,下面就是我们最终的成果。

   1: myListOfInstances =
   2:     (from file in Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins"), "*.dll")
   3:      let a = Assembly.LoadFrom(file)
   4:      from t in a.GetTypes()
   5:      where !t.IsAbstract && t.BaseType == typeof(MyBaseClass) 
   6:      select (MyBaseClass)Activator.CreateInstance(t, credentials))
   7:     .ToList();

这只有一行代码,留白是为了保证可读性。这些的含义和第一块代码一样,不过,读起来更简单。虽然我很喜欢这份代码,但在我看来,这不是最好的展示LINQ光芒的例子。显然在这个例子里,没什么地方可以让我加入一个错误处理代码,不能捕获加载错误或者类型转换错误,不过,在单行中却有很多空间,可以设置断点进行调试

Jeff运用的就是一个比较好的例子:

   1: var primes = new int[] { 2,3,5,7,11,13,17,19,13,29,31,37,41 };
   2: var primeSum = 0;
   3: for (int i = 0; i < primes.Length; i++)
   4: {
   5:   primeSum += primes[i];
   6: }

甚至可以…

   1: var primes = new int[] { 2,3,5,7,11,13,17,19,13,29,31,37,41 };
   2: var primeSum = 0;
   3: foreach (int i in primes)
   4: {
   5:   primeSum += i;
   6: }

写起来简单,读起来也简单:

   1: var primes = new int[] { 2,3,5,7,11,13,17,19,13,29,31,37,41 };
   2: var primeSum = primes.Sum();

.Sum()方法LINQ的一部分,它跟Array一样继承IEnumerable接口。

我大力推荐你们去下载免费版无需安装的LINQPad,里面包含了200个精彩的C#实例

下面给出的是些我认为很漂亮的一些示例代码,比起我通常写的标准代码绝对是一个进步:

   1: var names = new[] { "Tom", "Dick", "Harry" }.Where(n => n.Length >= 4);

这段语法清晰的代码能为列表做很多事情:

   1: string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
   2:  
   3: var results =
   4:      (
   5:        from n in names
   6:        where n.Contains("a")  // Filter elements
   7:        orderby n.Length       // Sort elements
   8:        select n.ToUpper()     // Translate each element (project)
   9:      ).ToList();       

你是否也写过What多于How的代码呢?

关于LINQ

LINQ to Everything - LINQ to XSD adds more LINQiness

Get namespaces from an XML Document with XPathDocument and LINQ to XML

Moq: Linq, Lambdas and Predicates applied to Mock Objects

Hanselminutes Podcast 79 - LINQ to XML

Improving LINQ Code Smell with Explicit and Implicit Conversion Operators

XLINQ to XML support in VB9

101 LINQ Samples

LINQ to Amazon

How Linq to Object Queries Work


Comments (0)

Skip to main content