代码改变世界

Linq学习之路(06) - Linq设计模式之ForEach模式

2013-05-19 11:46  ARMdong  阅读(1228)  评论(0编辑  收藏  举报

废话不多说,我们直接看一个demo:输出PageCount大于等于100页的所有Book的标题。

标准方法:

var books =
    from book in SampleData.Books
    where book.PageCount >= 100
    select book;

foreach (var book in books)
{
    Console.WriteLine(book.Title);
}

 

输出结果:

这段代码很简单,首先检索所有pageCount大于等100的书籍,然后遍历检索的结果,输出他们的书名。但是现在我有个需求,能不能在Linq query expression中直接输出书籍的标题呢?很可惜,Linq没有为我们提供这样的query operation或query expression。但是这里我们可以自己写方法,那么接下来我就跟大家一起来实现这样一个功能的扩展方法。

 

添加扩展方法:

大家有没有考虑这个方法应该添加到什么地方呢?能不能适用于所有的实体对象呢?假如我下次检索的不是Book,而是Student或者Product之类的呢?综合上述原因,我考虑把这个方法添加到System.Linq命名空间下面的Enumerable类中,作为它的扩展方法。

那么我们就来些这样的一个扩展方法,实现扩展方法的三要素大家应该都很清楚了,static class 、static method、this keyword。

我们在项目中添加一个IEnumerableExt类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//注意:这里一定要设置为System.Linq命名空间
namespace System.Linq
{
    //指定扩展方法要添加的类名
    public static class Enumerable
    {
        /// <summary>
        /// 扩展方法,遍历collection,并将每个element作为参数传到func方法里面
        /// </summary>
        /// <typeparam name="T">entity类型</typeparam>
        /// <param name="source">origin sequence</param>
        /// <param name="func">处理函数</param>
        public static void ForEach<T>(this IEnumerable<T> source, Action<T> func)
        {
            foreach (var item in source)
            {
                //实现某种功能的方法,我们这里用到的是输出book.Title
                func(item);
            }
        }
    }
}

 

接下来我们就改善我们一开始的那个demo:我们让query expression中实现foreach中实现的功能:

  (from book in SampleData.Books
   where book.PageCount >= 100
   select book)
     .ForEach(book => Console.WriteLine(book.Title)); 

 

输出结果:

就是这么简单,得到的结果和第一步完全相同,但是代码量明显减少,而且我们编写的扩展方法可以重复利用。那么接下来,我就实现Mulltiple Foreach Expression。

在每个Title后面都加上一段话:

SampleData.Books
    .Where(book => book.PageCount >= 100)
    .Select(book => book)
    .ForEach(book =>
        {
            book.Title += " (long)";
            Console.WriteLine(book.Title);
        });

 

输出结果:

 

小结:利用Linq Design Pattern 可以非常有效的进行代码复用,而且灵活性提高并且减少代码量。大家为何不用呢?