首页 > 代码库 > C# LINQ需求实现演化

C# LINQ需求实现演化

  Linq是C#3.0引入的,在C#2.0实现从集合中过滤符合条件的记录实现方式。

  假设有一个Book类,以及一个Book类的集合,现在需要从集合中查找出单价大于50的Book。

  1、固定查询字段的实现方式:

  Book.cs类:

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

namespace LINQTest
{
    public class Book
    {
        public string Title { get; set; }

        public decimal Price { get; set; }

        public string Author { get; set; }

        public string ISBN { get; set; }
    }
}

  Help.cs类:

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

namespace LINQTest
{
    public class Helper
    {
        public static IList<Book> SearchBookByPrice()
        {
            IList<Book> books = new List<Book> {
                new Book{Title="Book1", Author="Author1", ISBN="ISBN1", Price=30},
                new Book{Title="Book2", Author="Author2", ISBN="ISBN2", Price=40},
                new Book{Title="Book3", Author="Author3", ISBN="ISBN3", Price=50},
                new Book{Title="Book4", Author="Author4", ISBN="ISBN4", Price=60}
            };

            IList<Book> results = new List<Book>();
            foreach (Book book in books)
            {
                if (book.Price >= 50)
                {
                    results.Add(book);
                }
            }

            return results;
        }
    }
}

  Program.cs类:

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

namespace LINQTest
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (Book book in Helper.SearchBookByPrice())
            {
                Console.WriteLine("{0}-{1}", book.Title, book.Price);
            }
        }
    }
}

  上面的代码中实现了根据Price查询集合中大于50的记录。但是当需求有变动,需要根据Title来查询时,则上面的实现方法需要另外进行编写按Title查询的方法。

  2、不固定查询字段的实现方式

  查询条件最后返回的只是true或false,在新定义的方法中,只要if语句中返回为true的记录,添加到集合中即可,而不需要去知道具体是什么查询条件。

  Helper.cs类:

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

namespace LINQTest
{
    public class Helper
    {
        public delegate bool Condition(Book book);

        public bool ConditionTitle(Book book)
        {
            return book.Title == "Book2";
        }

        public bool ConditionPrice(Book book)
        {
            return book.Price >= 50;
        }

        public static IList<Book> SearchBookByCondition(Condition condition)
        {
            IList<Book> books = new List<Book> {
                new Book { Title = "Book1", Author = "Author1", ISBN = "ISBN1", Price = 30 },
                new Book { Title = "Book2", Author = "Author2", ISBN = "ISBN2", Price = 40 },
                new Book { Title = "Book3", Author = "Author3", ISBN = "ISBN3", Price = 50 },
                new Book { Title = "Book4", Author = "Author4", ISBN = "ISBN4", Price = 60 }
            };
            

            IList<Book> results = new List<Book>();

            foreach (Book book in books)
            {
                if (condition(book))
                {
                    results.Add(book);
                }
            }

            return results;
        }
    }
}

  Program.cs类:

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

namespace LINQTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //Helper.Condition condition = new Helper.Condition(new Helper().ConditionTitle);
            Helper.Condition condition = new Helper().ConditionTitle;
            foreach (Book book in Helper.SearchBookByCondition(condition))
            {
                Console.WriteLine("{0}-{1}", book.Title, book.Price);
            }
        }
    }
}

  以上的实现方式采用委托delegate,在C#2.0中还提供了匿名方法,集合中过滤查询条件的代码可修改为:

Helper.Condition condition = delegate(Book book) { return book.Title == "Book2"; };
IList<Book> results = Helper.SearchBookByCondition(delegate(Book book) { return book.Title == "Book2"; });

   在C#3.0提供了Lambda表达式,则实现集合过滤方式为:

IList<Book> results = Helper.SearchBookByCondition(book => book.Title == "Book2");

  但这样实现每次都要带类名Helper,我们希望IList自身就具有这个方法,C#3.0提供了扩展方法。

  3、C#3.0扩展方法实现方式

public static class Helper
{
    public delegate bool Condtion(Book book);
 
    public static IList<Book> Where(this IList<Book> books, Condtion condition)
    {
        IList < Book > results = new List<Book>();
        foreach (Book book in books)
        {
            if (condition(book))
            {
                results.Add(book);
            }
        }
        return results;
    }
}
IList<Book> results = books.Where(book => book.Title == "Book2");

  5、IEnumberable实现方式

  由于IList都继承自IEnumberable,则可以通过扩展IEnumberable来实现。

public static class Helper
{
    public delegate bool Condtion<T>(T t);
    public static IEnumerable<T> Where<T>(this IEnumerable<T> items, Condtion<T> condition)
    {
        foreach (T t in items)
        {
            if (condition(t))
            {
                yield return t;
            }
        }
    }
}

   6、通用扩展类

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

namespace LINQTest
{
    public class Extension
    {
        public delegate TResult Func<T, TResult>(T t);

        public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> filter)
        {
            foreach (T item in source)
            {
                if (filter(item))
                {
                    yield return item;
                }
            }
        }

        public static IEnumerable<TResult> Select<T, TResult>(this IEnumerable<T> source, Func<T, TResult> selector)
        {
            foreach (T item in source)
            {
                yield return selector(item);
            }
        }
    }
}
var result = books.Where(book => book.Title == "Book2").Select(book => new { 
                Key = book.Title,Value=http://www.mamicode.com/book.Price
            });