ASP.NET MVC 5 (五)c#的lambda表达式、LinQ和Async异步处理

来源:互联网 发布:java api接口编写实例 编辑:程序博客网 时间:2024/06/04 17:48

简单介绍Lambda表达式和LINQ表达式,详细的C#语言语法查阅一下两个链接,详细实验和解释另外再开一个语法系列。
Lambda 表达式(C# 编程指南)
来自 https://msdn.microsoft.com/zh-cn/library/bb397687.aspx

LINQ 查询表达式(C# 编程指南)
来自 https://msdn.microsoft.com/zh-cn/library/bb397676.aspx

  • Lambda表达式基本语法样式
  • 自动接口类型
  • 匿名类型
  • 执行语言集成查询LINQ
  • 一些LINQ扩展方法列表
  • 延迟的LINQ查询

Lambda表达式基本语法样式

参数列表=>表达式或语句块

符号”=>”读作“goes to”,它和赋值运算“=”有相同优先级,符号”=>”右侧的lambda表达式成为“表达式lambda”。
他有一下几种形式:

    • (int x,int y)=>x==y    //括号中多个参数之间用逗号隔开    • (x,y)=>x==y              //可以省略参数类型    • (int x)=>x>12           //一个参数可以省略括号    • x=>{string n=x+" "+"World";Console.WriteLine(n);}//语句块    • ()=>SomeMethod()     //无参表达式

表达式 Lambda 的主体可以包含一个方法调用。

当自己想调用自己的lambda表达式时可以使用委托调用,或者使用Func<>。

//定义委托 delegate int mydelegate(int x, int y);public static void Main(string []args){     mydelegate del = (x, y) =>  x * y ;    int total=del(12, 12);     //total==12*12==144}//Func<>参数  public static IEnumerable<Product> Filter(            this IEnumerable<Product> productEnum, Func<Product, bool> selectorParam)        {            foreach (Product prod in productEnum)            {                if(selectorParam (prod))                    yield return prod;            }        } public void UseFilterExtensionMethod()        {            IEnumerable<Product> products = new ShoppingCart            {                Products = new List<Product>{                    new Product{Name="kayak",Price=275M},                    new Product{Name="LifeJack",Price=48.95M},                    new Product{Name="Soccer",Category="Soccer",Price=19.58M},                    new Product{Name="Corner",Category="Soccer",Price=34.95M}                }            };            Func<Product, bool> categoryFilter = prod => prod.Category == "Soccer"|| prod.Price>20;    //检索满足条件:Category == "Soccer|| prod.Price>20“的元素组成集合            decimal total = 0, total1 = 0;            foreach (Product prod in products.Filter(categoryFilter))            {                total += prod.Price;            }    //求满足条件的单价之和        }

自动接口类型

使用var关键字定义局部变量而不必指定该变量类型,称为 类型推断 或 隐式类型。

var myVariable = new Product { Name="Kayak",Price=50};//合法int count = myVariable.Count;    //不合法,Product类没有该Count属性

匿名类型

可以不指定类型或结构,直接定义:

var myAnonType=new{Name="MVC",Category="Pattern"};

myAnonType是一个匿名类型对象,但它不是动态的,依旧是强类型,即只可以对初始化器”{}”中已经定义的属性进行赋值或取值,而不允许修改其定义。编译器进行编译时会对这种匿名类型生成一个类,具有相同属性名的两个匿名类型对象会被分配给同样的类。

执行语言集成查询(LINQ)

LINQ类似于SQL语句,用于在对象集合上进行查询数据。比如:
在上一章的LanguageFeatures项目的HomeController中添加如下代码:

 public ViewResult FindeProducts()        {            Product[] products = {                    new Product{Name="kayak",Category="Watesports",Price=275M},                    new Product{Name="LifeJack",Category="Watesports",Price=48.95M},                    new Product{Name="Soccer",Category="Soccer",Price=19.58M},                    new Product{Name="Corner",Category="Soccer",Price=34.95M}                };        //LINQ语句,从products查询对象并按Prcie降序排列并只获取前三个,查询结果对象的Name属性和Price属性重新组成一个新的类型对象        var foundProducts = from match in products                            orderby match.Price descending                            select new { match.Name, match.Price };                string result = "";        int i = 0;       foreach (var prod in foundProducts)       {           i++;           if (i >3)               break;           result += prod.Name + ":" + prod.Price + " ";       }        return View("Result",(object)result);    }

运行并导航到/home/FindeProducts会得到结果:
kayak:275 LifeJack:48.95 Corner:34.95

上述代码类似于SQL语句,这种风格称为 查询语法,它用起来舒服简单,但它为每一个源数据组中的每个Product返回一个匿名对象,需要另外进行处理。
LINQ还有另外的一种风格,叫做 点符号语法,它是基于扩展方法的。比如将上述代码替换为如下代码可以实现同样的代码:

 public ViewResult FindeProducts()        {            Product[] products = {                    new Product{Name="kayak",Category="Watesports",Price=275M},                    new Product{Name="LifeJack",Category="Watesports",Price=48.95M},                    new Product{Name="Soccer",Category="Soccer",Price=19.58M},                    new Product{Name="Corner",Category="Soccer",Price=34.95M}                };            /*LINQ语句,从products查询对象并按Prcie降序排列,查询结果对象的Name属性和Price属性重新组成一个新的类型对象*/            var foundProducts = products.OrderByDescending(e => e.Price)                .Take(3).Select(e => new { e.Name, e.Price });            string result = "";           foreach (var prod in foundProducts)           {               result += prod.Name + ":" + prod.Price + " ";           }            return View("Result",(object)result);        }

一些LINQ扩展方法列表

摘自《精通ASP.NE MVC5》([美]Adam Freeman 著,张成彬等译)

扩展方法 描述 延迟 All 如果源数据中所有的条目都与谓词匹配,则返回true 否 Any 如果源数据中至少有一个条目与谓词匹配,则返回true 否 Contains 如果数据源含有指定的条目或值,则返回true 否 Count 返回数据源的条目数 否 First 返回数据源的第一个条目 否 FirstOrDefault 返回数据源的第一个条目,或无条目时返回默认值 否 Last 返回数据源的最后一个条目 否 LastOrDefault 返回数据源的最后条目,或无条目时返回默认值 否 Max
Min 返回lambda表达式表达的最大值或最小值 否 OrderBy
OrderByDescending 基于lambda表达式返回的值对源数据进行排序 是 Reverse 反转数据源中的数据项的顺序 是 Select 设计一个查询结果 是 SelectMany 把每一个数据项投射到一个条目序列之中,然后把所有这些结果序列连接成一个序列 是 Single 返回数据源的第一个条目,或者有多个匹配时抛出异常 否 SingleOrDefault 返回数据源的第一个条目,或者无条目时,返回默认值;有多个匹配条目时,抛出一个异常 否 Skip
SkipWhile 跳过指定书目的元素,或者当谓词匹配时跳过 是 Sum 对谓词选定的值求和 否 Take
TakeWhile 从数据源的开始出选择指定条目的元素,或当谓词匹配是选择条目 是 ToArray
ToDictionary
ToList 把数据源转换成数组或其他集合类型 否 Where 过滤掉数据源数据中与谓词不匹配的条目 是

延迟的LINQ查询

延迟的意思是,直到对结果进行枚举后,才会执行该查询,每次对记过进行枚举时都会从头求取查询结果。如:

Product[] products = {                            new Product{Name="kayak",Category="Watesports",Price=275M},                            new Product{Name="LifeJack",Category="Watesports",Price=48.95M},                            new Product{Name="Soccer",Category="Soccer",Price=19.58M},                            new Product{Name="Corner",Category="Soccer",Price=34.95M}                        };         var foundProducts = products.OrderByDescending(e => e.Price)                        .Take(3).Select(e => new { e.Name, e.Price });                    string result = "";//延迟的LINQ查询定义的位置products[2]=new Product{Name="kayak1",Category="Watesports",Price=276M};                //修改数据源           foreach (var prod in foundProducts)           {               result += prod.Name + ":" + prod.Price + " ";           }//枚举查询结果,它会显示修改数据源之后的结果

在定义LINQ查询得位置和修改数据源的位置分别插入断点,两个断点出查看foundProducts会发现发生了改变,尽管初始化foundProducts之后并没有对foundProducts进行更改,只是更改了源数据而已,此时延迟的LINQ这一特性便展现出来了。

使用async和await关键字是一种简单的异步处理方法。
如:

using System;using System.Net.Http;using System.Threading.Tasks;using System.Collections.Generic;using System.Linq;using System.Web;namespace LanguageFeatures.Models{    public class MyAsyncMethods    {       public async static Task<long?> GetPageLength()        {            HttpClient client = new HttpClient();            var httpMessage = await client.GetAsync("http://apress.com");            return httpMessage.Content.Headers.ContentLength;        }    }}

代码中使用了await关键字,它告诉编译器希望程序等待GetAsync方法返回的Task结果并继续执行同一方法中的其他语句。当使用await关键字时必须对该方法的的签名添加async关键字。但若想使用MVC控制器使用异步方法需要一项特殊技术,因此这里没有给出。这里只是想简单介绍一下async和await关键字的作用而已。

1 0