续上面

///<summary>/// 定义一个静态类,用于实现扩展方法///</summary>publicstaticclass MyExtensionMethods {
///<summary>
/// 商品查询器
///</summary>
///<param name="productEnum">扩展类型的实例引用</param>
///<param name="selectorParam">一个参数类型为Product,返回值为bool的委托</param>
///<returns>查询结果</returns>
public static IEnumerable<Product> Filter(this IEnumerable<Product> productEnum, Func<Product bool> selectorParam) {
foreach (Product prod in productEnum) {
if (selectorParam(prod)) {
yieldreturn prod;
            }
        }
    }
}

没错,我们就是用这么简短的Filter方法来满足各种需求的查询。上面Product类使用的是前文定义的。这里也再一次见证了扩展方法的功效。为了演示Filter查询方法的调用,我们先来造一批数据:

staticvoid Main(string[] args) {
// 创建商品集合
    IEnumerable<Product> products = new ShoppingCart {
        Products = new List<Product> { 
new Product {Name = "西瓜", Category = "水果", Price = 2.3M}, 
new Product {Name = "苹果", Category = "水果", Price = 4.9M}, 
new Product {Name = "ASP.NET MCV 入门", Category = "书籍", Price = 19.5M}, 
new Product {Name = "ASP.NET MCV 提高", Category = "书籍", Price = 34.9M} 
        }
    };
}

接下来我们继续在上面Main方法中来调用查询方法Filter:
//用匿名函数定义一个具体的查询需求

Func<Product, bool> fruitFilter = delegate(Product prod) {
return prod.Category == "水果";
};

//调用Filter,查询分类为“水果”的商品

IEnumerable<Product> filteredProducts = products.Filter(fruitFilter);
//打印结果foreach (Product prod in filteredProducts) {
    Console.WriteLine("商品名称: {0}, 单价: {1:c}", prod.Name, prod.Price);
} 
Console.ReadKey();

上面我们使用的是委托和匿名函数来处理用户查询逻辑,并把它传递给Filter方法,满足了前面所说的需求。但若使用Lambda表达式代替上面的匿名函数能使上面的代码看上去更简洁更人性化,如下代码所示:

Func<Product, bool> fruitFilter = prod => prod.Category == "水果";
IEnumerable<Product> filteredProducts = products.Filter(fruitFilter);

没有了delegate关键字,没有了大小括号,看上去更舒服。当然上面两行代码可以继续简化为一行:

IEnumerable<Product> filteredProducts = products.Filter(prod => prod.Category == "水果");

这三种方式输出结果都是一样的。然后,我们还可以通过Lambda表达式实现各种需求的查询:
//查询分类为“水果”或者单价大于30元的商品

IEnumerable<Product> filteredProducts = products.Filter(prod =>
    prod.Category == "水果" || prod.Price >30
);

6.LINQ
最后简单回顾一下LINQ。LINQ(Language Integrated Query语言集成查询)是 VS 2008 和 .NET Framework 3.5 版中一项突破性的创新,它在对象领域和数据领域之间架起了一座桥梁。
上面讲Lambda表达式时,用到的查询结果集的方式未免还是有点麻烦(因为自定义了一个Filter扩展方法),而Linq本身就集合了很多扩展方法,我们可以直接使用,大大的简化了编写查询代码的工作。例如,对于这样一个数据集合:

Product[] products = {
new Product {Name = "西瓜", Category = "水果", Price = 2.3M}, 
new Product {Name = "苹果", Category = "水果", Price = 4.9M}, 
new Product {Name = "空心菜", Category = "蔬菜", Price = 2.2M}, 
new Product {Name = "地瓜", Category = "蔬菜", Price = 1.9M} 
};

如果要查询得到价钱最高的三个商品信息,如果不使用Linq,我们可能会先写一个排序方法,对products根据价钱由高到低进行排序,排序时需要创建一个新的Product[]对象用于存储排序好的数据。但用Linq可大大减少工作量,一两句代码就能搞定。如下代码所示,查出价钱最高的三个商品:

var results = from product in products
orderby product.Price descending
selectnew {
                    product.Name,
                    product.Price
                };//打印价钱最高的三个商品
int count = 0;
foreach (var p in results) {
    Console.WriteLine("商品:{0},价钱:{1}", p.Name, p.Price);
if (++count == 3) break;
}
Console.ReadKey();

能熟练使用Linq是一件很爽的事情。上面的Linq语句和我们熟悉的SQL查询语句类似,看上去非常整洁且易懂。但并不是每一种SQL查询语句在C#都有对应的关键字,有时候我们需要使用另外一种Linq查询方式,即“点号”方式的Linq查询方式,这种方式中的Linq查询方法都是扩展方法。如下面这段代码和上面实现的效果是一样的:

var results = products
    .OrderByDescending(e => e.Price)
    .Take(3)
    .Select(e =>new { e.Name,e.Price});
foreach (var p in results) {
    Console.WriteLine("商品:{0},价钱:{1}", p.Name, p.Price);
}
Console.ReadKey();

虽然类SQL的Linq查询方式比这种方式看上去更一目了然,但并不是每一种SQL查询语句在C#都有对应的关键字,比如这里的Take扩展方法就是类SQL的Linq查询语法没有的功能。
注意,有些Linq扩展方法分为“延后查询”(deferred)和“即时查询”(immediate)。延后查询意思是拥有“延后查询”扩展方法的Linq语句只有当调用结果集对象的时候才开始真正执行查询,即时查询则是立即得到结果。比如上面的Linq语句的OrderByDescending扩展方法就是一个“延后查询”方法,当程序执行到Linq语句定义部分时并没有查询出结果并放到results对象中,而是当程序执行到foreach循环时才真正执行Linq查询语句得到查询结果。我们可以做个测试,在Ling语句之后,我们再将products[1]对象重新赋值,如下代码所示:

var results = products
    .OrderByDescending(e => e.Price)
    .Take(3)
    .Select(e =>new { e.Name, e.Price });
//在Linq语句之后对products[1]重新赋值
products[1] = new Product { Name = "榴莲", Category = "水果", Price = 22.6M };
//打印foreach (var p in results) {
    Console.WriteLine("商品:{0},价钱:{1}", p.Name, p.Price);
}
Console.ReadKey();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值