您的位置:时时app平台注册网站 > 编程知识 > C#中匿名函数、委托delegate和Action、Func、Expressi

C#中匿名函数、委托delegate和Action、Func、Expressi

2019-11-03 03:24

总结

1、都以指望可以单独援用风姿洒脱段代码片引起的。
2、然后援用了信托delegate,delegate的使用办法为表明类型-实例化类型(传入想要使用的类的法子卡塔尔国-使用委托(使用方法)
3、简化操作,使用(通过Lambda只怕delegate卡塔尔无名格局来一直声圣元(Synutra卡塔 尔(阿拉伯语:قطر‎段代码片,幸免表明所想使用的类的艺术
4、简化操作,直接使用C#预约义的二种委托Action、Func、Predicate,连证明委托都省了。
5、本文代码:

六、总结

    Delegate起码0个参数,至多35个参数,能够无重临值,也得以钦赐重返值类型

  Func能够选用0个至20个传入参数,必须怀有重临值

  Action可以选择0个至十六个传入参数,无再次来到值

  Predicate只好选择贰个传播参数,再次回到值为bool类型

 

参照小说:

1.3 佚名类的分享

  能够想像一下,假诺大家的代码中定义了大多佚名类,那么是或不是编写翻译器会为每三个无名氏类都生成三个泛型类呢?答案是不是认的,编译器思虑得相当远,幸免了再度地生成类型。换句话说,定义了七个无名类的话要是切合一定标准绳足以分享叁个泛型类。上面,我们就来拜候有哪二种景况:

  (1卡塔 尔(英语:State of Qatar)即使定义的无名氏类与事先定义过的千篇一律:属性类型和黄金年代豆蔻年华都如出风姿洒脱辙,那么暗中认可分享前三个泛型类

时时app平台注册网站 1)

                    var annoyCla1 = new


            {

                ID = 10010,

                Name = "EdisonChou",

                Age = 25


            };

 

            Console.WriteLine("ID:{0}-Name:{1}-Age:{2}", annoyCla1.ID,

                annoyCla1.Name, annoyCla1.Age);

            Console.WriteLine(annoyCla1.ToString());

 

                        // 02.属性类型和顺序与annoyCla1一致,那么共同使用一个匿名类


                    var annoyCla2 = new


                {

                    ID = 10086,

                    Name = "WncudChou",

                    Age = 25


                };

            Console.WriteLine("ID:{0}-Name:{1}-Age:{2}", annoyCla1.ID,

                annoyCla1.Name, annoyCla1.Age);

            Console.WriteLine("Is The Same Class of 1 and 2:{0}",

                annoyCla1.GetType() == annoyCla2.GetType());    

时时app平台注册网站 2)

  通过上述代码中的最终两行:我们能够看清其是或不是是一个体系?答案是:True

时时app平台注册网站 3

  (2卡塔 尔(阿拉伯语:قطر‎倘诺属性名称和生机勃勃风姿浪漫生机勃勃致,但品质类型差异,那么照旧生机勃勃道接纳两个泛型类,只是泛型参数改变了而已,所以在运行时会生成不同的类:

时时app平台注册网站 4)

                    var annoyCla3 = new


                {

                    ID = "EdisonChou",

                    Name = 10010,

                    Age = 25


                };

            Console.WriteLine("ID:{0}-Name:{1}-Age:{2}", annoyCla3.ID,

                annoyCla3.Name, annoyCla3.Age);

            Console.WriteLine("Is The Same Class of 2 and 3:{0}",

                annoyCla3.GetType() == annoyCla2.GetType());

时时app平台注册网站 5)

  咱们恰好谈到即便分享了同三个泛型类,只是泛型参数改造了而已,所以在运行时会生成不同的类。所以,那么能够估算到最终两行代码所出示的结果应该是False,他们就算都选取了一个泛型类,不过在运转时生成了五个不等的类。

时时app平台注册网站 6

  (3卡塔 尔(英语:State of Qatar)假设数据型名称和连串相近,但顺序差异,那么编写翻译器会再也创制二个无名氏类

时时app平台注册网站 7)

                    var annoyCla4 = new


                {

                    Name = "EdisonChou",

                    ID = 10010,

                    Age = 25


                };

            Console.WriteLine("ID:{0}-Name:{1}-Age:{2}", annoyCla4.ID,

                annoyCla4.Name, annoyCla4.Age);

            Console.WriteLine("Is The Same Class of 2 and 4:{0}",

                annoyCla4.GetType() == annoyCla2.GetType());

时时app平台注册网站 8)

  运维判别结果为:False

时时app平台注册网站 9

  通过Reflector,能够窥见,编写翻译器确实重新生成了四个泛型类:

时时app平台注册网站 10

 

二、Delegate

   Delegate起码0个参数,至多34个参数,能够无重返值,也足以钦命再次回到值类型。

     public delegate int MethodDelegate(int x, int y);
        private static MethodDelegate method;
        static void Main(string[] args)
        {
            method = new MethodDelegate(Add);
            Console.WriteLine(method(10,20));
            Console.ReadKey();
        }

        private static int Add(int x, int y)
        {
            return x   y;
        }

 

排山倒海计算

  转须臾,四篇文章的介绍就到此停止了,其实本体系介绍的都以不算新语法,其实也能够说成是老语法了。说它们新,只然则是对峙于.NET老版本来说,何况平日付出中山大学家有希望未有专一到的有个别细节,本体系做了八个简便的介绍。目前看见不菲田园里的童鞋初叶关心C# 6.0的新性子了,粗略看了看,语法糖居多,相信经过了那意气风发系列的探秘,对于新的语法糖,大家能够站在三个相比较高的可观去对待它们。最终,多谢各位园友的浏览,以致给自家的生龙活虎对砥砺,再次多谢!

无名氏方式二种完成情势:

一、简介

  委托是生机勃勃种档期的顺序,由第一字delegate证明。确切的说,委托是后生可畏种可用以封装命名或然佚名格局的引用类型。  它就疑似于 C 中的函数指针,况兼是项目安全和可信赖的。

  委托项指标宣示与艺术签字雷同,有一个重临值和专断数目恣意等级次序的参数。必得接收全数优越再次回到类型和输入参数的办法或 lambda 表明式实例化委托。

  委托允许将艺术作为参数进行传递。
  委托可用于定义回调方法。
  委托能够链接在一块儿;比方,能够对二个事件调用多少个法子。
  方法不必与寄托具名完全合营。

三、扩展方法:[ C# 3.0/.NET 3.x 新添特色 ]

寄托需求先声澳优(Ausnutria Hyproca卡塔尔个项目本领利用,那很麻烦,举个例子自身在某四个命名空间证明了叁个从未重临值的委托myDelegate,然后想要那一个委托的时候,各个命名空间都要援用那么些命名空间,那太不协和了。

五、Predicate<T>

 泛型委托:表示定义大器晚成组条件并规定钦命对象是不是合乎那一个原则的点子。此委托由 Array 和 List 类的两种格局运用,用于在聚聚焦寻找成分。

void Main(string[] args)
        {
            Point[] points = { new Point(100, 200), 
            new Point(150, 250), new Point(250, 375), 
            new Point(275, 395), new Point(295, 450) };
            Point first = Array.Find(points, ProductGT10);
            Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);
            Console.ReadKey();
        }
        private static bool ProductGT10(Point p)
        {
            if (p.X * p.Y > 100000)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

选取含有 Array.Find 方法的 Predicate 委托找寻 Point 结构的数组。

只要 X 和 Y 字段的乘积大于 100,000,此委托代表的办法 ProductGT10 将回来 true。

Find 方法为数组的种种成分调用此委托,在契合测量试验条件的第一个点处结束。

2.2 引进无名氏方式

  (1卡塔尔首先,大家来看看下边包车型大巴事举例何运用无名情势来得以完结:

DelegateTest dgTest2 = new DelegateTest(delegate(string name)

{

      Console.WriteLine("Good,{0}", name);

});

时时app平台注册网站 11

从运维结果图中能够看见,原本要求传递方式名的地点大家从来传送了三个方法,那么些措施以delegate(参数){方法体}的格式编写,在{}里边直接写了方法体内容。于是,大家不由自己作主心花怒放,又能够简化一些职业量咯!

  (2卡塔 尔(英语:State of Qatar)其次,大家将扭转的主次通过Reflector反编写翻译看看匿超级模特式是怎么帮大家落实命有名的模特式的功能的。

  ①大家能够观望,在编写翻译生成的类中,除了大家友好定义的诀要外,还多了五个无缘无故的成员:

时时app平台注册网站 12

  ②透过逐生机勃勃查看,原本编写翻译器帮大家转换了三个民用的寄托对象以至一个民用的静态方法。大家可以大胆猜度:原本无名方式不是还未名字的点子,还是生成了叁个出名字的主意,只可是那几个格局的名字被隐形起来了,并且方式名是编写翻译器生成的。

时时app平台注册网站 13

时时app平台注册网站 14

  ③透过地点的解析,大家照旧不甚理解,到底匿有名的模特式委托对象在程序中是怎么显示的?这里,大家需求查阅Main方法,不过经过C#代码我们未有发掘一些足以协助大家明白的。这时候,大家想要刨根问底就有一些麻烦了。辛亏,在高人携遗精,大家明白能够依赖IL(中间代码卡塔尔来剖判一下。于是,在Reflector中切换展现语言,将C#改为IL,就能够看出其它生龙活虎番世界。

时时app平台注册网站 15

  (3卡塔尔由地点的解析,大家能够做出结论:编写翻译器对于佚名形式帮大家做了两件事,一是生成了一个个体静态的信托对象和叁个民用静态方法;二是将转移的不二秘技的地点存入了委托,在运营时调用委托对象的Invoke方法奉行该信托对象所持有的方法。由此,大家也足以看来,无名方式需求组合委托行使

Action、Func、Predicate

四、Action<T>

Action 委托:未有传到参数,也还未有回去类型,即Void。如:

void Main(string[] args)
        {
            Action say = SayHello;
            say();
        }
        public static void SayHello( )
        {
           Console.WriteLine("Say Hello");
        }

Action<T> 信托:传入参数为T,未有回到类型。如:

void Main(string[] args)
        {
            Action<string> say = SayHello;
            say("Hello");
        }
        public static void SayHello(string word )
        {
            Console.WriteLine(word);
        }

其实ActionFunc的用法大约,差距只是二个有再次回到类型,三个从未有过回到类型,当然Action也能够接佚名方法和Lambda表达式。

匿超级模特式:

void Main(string[] args)
        {
            Action<string> say = delegate(string word)
            {
                Console.WriteLine(word);
            };
            say("Hello Word");
        }

Lambda表达式:

 static void Main(string[] args)
        {
            Action<string> say = s => Console.WriteLine(s);
            say("Hello Word");
        }

 

1.2 深入Action

  在实质上支出中,大家平日将叁个信托实例作为叁个艺术的参数进行传递,于是我们来看一下那几个天下无双的风貌,再经过Reflector反编写翻译工具查看编写翻译器到底帮大家做了哪些遗闻宜!

  (1卡塔 尔(阿拉伯语:قطر‎首先来看一下在List集结类型的ForEach方法的概念:

时时app平台注册网站 16)

                    //


                        // 摘要:

        //     对 System.Collections.Generic.List<T> 的每个元素执行指定操作。


        //


                        // 参数:

        //   action:

        //     要对 System.Collections.Generic.List<T> 的每个元素执行的 System.Action<T> 委托。


        //


                        // 异常:

        //   System.ArgumentNullException:

        //     action 为 null。


                        public
                                void ForEach(Action<T> action);

时时app平台注册网站 17)

  能够看看,ForEach方法的参数是三个Action委托实例,也正是说是多个无再次来到值的委托实例。

  (2卡塔 尔(阿拉伯语:قطر‎定义一个实体类,并因而Action委托行使ForEach方法:

时时app平台注册网站 18 View Code

  能够见到,我们为ForEach方法传递了八个Action委托的实例,本质上是三个无重临值的措施指针,遍历输出了每种Person对象的讯息。

  时时app平台注册网站 19

  (3卡塔 尔(英语:State of Qatar)也可能有一点童鞋见到下面的依旧有一点不解,只要您精通过委托,那么我们能够通过Reflector反编译工具去看看编写翻译器到底做了啥事,Action委托的实质就能够一如精晓:(这里大家得以先看看未有Action的做法,是或不是亟需首先显式注明了叁个无重临值的嘱托,然后是否还要顶一个命名的无重返值的办法?卡塔 尔(阿拉伯语:قطر‎

  ①将编写翻译好的程序集拖动到Reflector中,可以见见以下的图景:

时时app平台注册网站 20

  ②现在各自造访编写翻译器为大家自动生成的无重临值的寄托定义和办法定义:

时时app平台注册网站 21

时时app平台注册网站 22

  能够见见,不管是自动生成的寄托依旧艺术,都以不带重临值的。

  ③有了地方的分析,我们再来看看施行的话语是怎么被编写翻译的:

时时app平台注册网站 23

   能够看见,在编写翻译后的代码里边连new Action<Person>()都省掉了,大家也得以精晓,在代码中得以更进一层简化。但是,首先,大家得询问到底编写翻译器是怎么识别Action委托的。于是,依据前两篇的思绪,在反编写翻译后的C#代码看不出什么线索的时候,切换成IL代码生龙活虎探毕竟:

时时app平台注册网站 24

  由IL代码可以看见,照旧原先的章程,依旧原先的意味。委托依旧极其务委员会委员托,试行委托依旧执行那一个方式。这里,大家再来看看List类型的ForEach方法是怎么采纳Action委托的:

时时app平台注册网站 25

  现在,大家能够了解,原来所不解的事物将来好不容易放心了:在ForEach会通过叁个巡回遍历依次调用委托所负有的艺术,那一个主意是三个符合Action委托定义的无再次来到值方法。至于,为何大家可以省略new Action<T>(),则是编写翻译器为我们提供的叁个惠及。比如,大家在使用List<Person>对象的ForEach方法时,大家得以如此写:

personList.ForEach(delegate(Person p)

{

      Console.WriteLine(p.ID   "-"   p.Name   "-"   p.Age);

});

  首先,由于大家是利用的personList这一个目的(List<Person>类型卡塔 尔(阿拉伯语:قطر‎,所以编写翻译器自动识别了泛型委托的T(即钦点项目卡塔尔国为Person。其次,编写翻译器自动将无重临值的佚名格局转变为了new Action<Person>对象。当然,假使是有重临值的无名情势则会转移为内定项目标new Func<T>()对象,这里因为ForEach只接纳无参数的嘱托实例或艺术,所以意气风发旦传入了有重返值的无名氏情势则会报错。

地点已经讲到无名函数了。函数和方法等价,用来封装后生可畏段代码片以便任何时候使用,有的有再次来到值有的无重临值。写在类里面。

三、Func<T>

 在使用 Func<T, TResult> 委托时,不必显式定义几个包装唯有二个参数的办法的信托。

 以下示例简化了此代码,它所用的措施是实例化 Func<T, TResult> 委托,并非显式定义三个新委托并将命名方式分配给该信托。

public class GenericFunc
{
   public static void Main()
   {
      // 依旧是用命名方法实例化委托类型
      Func<string, string> convertMethod = UppercaseString;
      string name = "Dakota";
      // 依旧是通过委托实例调用该方法
      Console.WriteLine(convertMethod(name));
   }

   private static string UppercaseString(string inputString)
   {
      return inputString.ToUpper();
   }
}

下边包车型大巴亲自过问演示怎样表明和行使 Func<T, TResult> 委托。  

此示例声美素佳儿(Friso卡塔 尔(阿拉伯语:قطر‎个 Func<T, TResult> 变量,并为其分配了二个将字符串中的字符转变为题写的 lambda 表明式。  

接着将封装此方法的寄托传递给Enumerable.Select 方法,以将字符串数组中的字符串改善为大写。

static class Func
{
   static void Main(string[] args)
   {
      // 声明了一个Func委托类型的变量selector并用Lambda表达式进行实例化 
      // 这个Lambda表达式将用来获取一个字符串并将这个字符串转化为大写并返回
      Func<string, string> selector = str => str.ToUpper();

      // 创建一个字符串数组
      string[] words = { "orange", "apple", "Article", "elephant" };
      // 依次遍历这个字符串数组并调用委托实例selector进行处理
      IEnumerable<String> aWords = words.Select(selector);

      // 输出结果到控制台
      foreach (String word in aWords)
         Console.WriteLine(word);
   }
}      
/*
This code example produces the following output:

   ORANGE
   APPLE
   ARTICLE
   ELEPHANT
*/

 

1.1 倒霉意思,作者匿了

   在支付中,大家一时会像上边包车型大巴代码近似声惠氏个无名类:能够见见,在无名氏类的语法中并从未为其命名,而是直接的二个new { }就到位了。从外表看来,我们根本无法知道那个类是干神马的,也不知情它有什么意义。

时时app平台注册网站 26)

                    var annoyCla1 = new


    {

        ID = 10010,

        Name = "EdisonChou",

        Age = 25


    };

 

    Console.WriteLine("ID:{0}-Name:{1}-Age:{2}", annoyCla1.ID,annoyCla1.Name, annoyCla1.Age);

时时app平台注册网站 27)

  经过调节和测量试验运维,咱们开掘无名类完全能够兑现具名类的功效:

时时app平台注册网站 28

上面已经经过无名函数实现了不要表明类,以往因而C#预约义的寄托项目达成了不用评释委托项目,那么未来就能够直接写代码片来奉行了

  2.2.1 用法先行:爽一下

  我们早就精通Func委托是带钦命重返值类型的寄托,那么大家来拜候在骨子里花费境况的生机勃勃幕。依然以刚刚那多少个数据集合PersonList为例,在不菲时候我们须求对从数据库中读取的数据集合举办一回筛选,那时大家得以运用List集结的Select方法,大家将一个Func委托实例作为艺术参数字传送递给Select方法,就足以回来二个切合我们内定条件的新数据集结。

  (1卡塔 尔(英语:State of Qatar)先来拜访Select方法的定义:

时时app平台注册网站 29)

                    //


                        // 摘要:

        //     将序列中的每个元素投影到新表中。


        //


                        // 参数:

        //   source:

        //     一个值序列,要对该序列调用转换函数。


        //


                    //   selector:

        //     应用于每个元素的转换函数。


        //


                        // 类型参数:

        //   TSource:

        //     source 中的元素的类型。


        //


                    //   TResult:

        //     selector 返回的值的类型。


        //


                        // 返回结果:

        //     一个 System.Collections.Generic.IEnumerable<T>,其元素为对 source 的每个元素调用转换函数的结果。


        //


                        // 异常:

        //   System.ArgumentNullException:

        //     source 或 selector 为 null。


                        public
                                static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector);

时时app平台注册网站 30)

  能够看看,Select方法中的参数接受了Func泛型委托,依照泛型委托的定义TSource和TResult分别代表要传播的数据类型以致要回去的数据类型。

  (2卡塔尔再来看看哪些在先后中动用Func委托:

  首先定义多少个与源数据类型分歧的新数据类型作为再次来到值类型:

                    public
                            class LitePerson

    {

                    public
                            string Name { get; set; }

    }

  ①标准定义版:

时时app平台注册网站 31)

            List<Person> personList = GetPersonList();

 

            IEnumerable<LitePerson> litePersonList = personList.Select<Person, LitePerson>(

                    new Func<Person, LitePerson>

                (

                    delegate(Person p)

                    {

                    return
                            new LitePerson() { Name = p.Name };

                    }

                )

            );    

时时app平台注册网站 32)

  ②哟哈简化版:依赖理编辑译器提供的自动识别,简化大家的代码

            IEnumerable<LitePerson> litePersonList = personList.Select(

                    delegate(Person p)

                {

                    return
                            new LitePerson() { Name = p.Name };

                }

            );

  ③绝逼懒人版:依赖无名氏类和泛型能够大大简化大家的代码

                    var liteList = personList.Select(delegate(Person p)

            {

                    return
                            new { Name = p.Name, AddDate = DateTime.Now };

            });

  (3卡塔 尔(阿拉伯语:قطر‎调节和测验运营能够获取以下结果:

时时app平台注册网站 33

Expression

1.1 初识Action

MSDN交给的定义:包装三个艺术,该形式不富有参数並且不再次来到值

  能够使用此委托以参数形式传递形式,而不用显式注解自定义的嘱托。封装的主意必须与此委托定义的主意具名相对应。也便是说,封装的秘籍不得持有参数,並且不得重临值。(在 C# 中,该办法必得回到 void卡塔 尔(英语:State of Qatar)日常,这种办法用于实行有个别操作。

  以往,大家来拜访哪些使用Action委托:

  (1卡塔 尔(英语:State of Qatar)先看看前边大家是怎么来利用无重返值委托的例子:

时时app平台注册网站 34 View Code

  能够领略地看出,我们事先要先显式证明了三个名叫 ShowValue 的寄托,并将对 Name.DisplayToWindow 实例方法的引用分配给其委托实例。

  (2卡塔 尔(阿拉伯语:قطر‎再看看有了Action委托随后我们怎么来完结地方的功用的事例:

时时app平台注册网站 35 View Code

  能够明白地看出,今后应用 Action 委托时,不必显式定义一个打包无参数过程的寄托。

delegate委托

  2.1.2 有了Func后的行使

时时app平台注册网站 36 View Code

  当然,我们还足以信赖无名氏格局尤其简便易行地利用:

时时app平台注册网站 37 View Code

  能够驾驭地看出,未来选拔 Func 委托时,不必显式定义叁个新委托并将命名方式分配给该信托。

原先平昔凌乱不堪的,以后到底搞通晓。

  2.2.2 原理为王:探二回

  (1卡塔尔国通过Reflector反编写翻译,大家再来看看编写翻译器帮我们转变的东东:

时时app平台注册网站 38

  (2卡塔尔国看看自动生成的嘱托和情势的定义:

时时app平台注册网站 39

时时app平台注册网站 40

  相信通过上节Action的详细深入分析,这里大家应该也足以闻一知十掌握编译器帮大家究竟做了怎么事情了,这里自个儿就不再赘述了,后边也不会再赘述此方面包车型地铁东东(为了省去页面大小卡塔 尔(英语:State of Qatar)。

  当然,和Action形似,.NET基类库为我们也提供了多达16个输入参数的Func委托,可是,输出参数却唯有1个。

        public delegate void Seep();
        static void Main(string[] args)
        {
            Seep see = delegate () { Console.WriteLine(1); };
        }

  5.1.2 拉姆da使用示例

时时app平台注册网站 41 View Code

   调试运维的结果如下:

时时app平台注册网站 42

无名函数总是和嘱托一同使用,因为佚名函数方便了寄托的使用(不用注明风流浪漫(Wissu卡塔 尔(阿拉伯语:قطر‎个类了卡塔 尔(阿拉伯语:قطر‎

1.3 排序小生OrderBy方法

  说起排序,我们马上想起了SQL中的order by语句,而行业内部查询运算符中也为大家提供了OrderBy那个办法,值得风度翩翩提的就是我们得以拓宽多规格的排序,因为OrderBy方法重临的依然是二个IEnumerable<T>的类型,还是能够世袭使用扩张方法。但要注意的是,第一遍应该选拔ThenBy方法。

时时app平台注册网站 43)

                    static
                            void SQOOrderByDemo()

        {

            List<Person> personList = GetPersonList();

                        // 单条件升序排序


            Console.WriteLine("Order by Age ascending:");

            List<Person> orderedList = personList.OrderBy(p => p.Age).ToList();

            orderedList.ForEach(p => Console.WriteLine(p.ToString()));

                        // 单条件降序排序


            Console.WriteLine("Order by Age descending:");

            orderedList = personList.OrderByDescending(p => p.Age).ToList();

            orderedList.ForEach(p => Console.WriteLine(p.ToString()));

                        // 多条件综合排序


            Console.WriteLine("Order by Age ascending and ID descending:");

            orderedList = personList.OrderBy(p => p.Age)

                .ThenByDescending(p => p.ID).ToList();

            orderedList.ForEach(p => Console.WriteLine(p.ToString()));

        }

时时app平台注册网站 44)

  运营结果如下图所示:

时时app平台注册网站 45

寄托还应该有生龙活虎部分特征(如可加性卡塔尔国,感兴趣的能够查看有关质地。

5.3 语句Lambda

  拉姆da表明式有两种类型:一是Lambda表明式,二是语句Lambda。时时app平台注册网站 46

  那么,语句Lambda和表达式Lambda到底有啥差异?

ANSWER:语句拉姆da 和 表明式拉姆da 的分别在于,前面三个在 =>右侧有三个语句块(大括号),而前者唯有三个表明式(未有return 和大括号)。

EXAMPLES:

(1)表达式Lambda:

list.FindAll(d => d.Id > 2);// goes to


list.ForEach(d => Response.Write(d.ToString()   "<br/>"));

(2)语句Lambda:

list.ForEach(d => { if (d.Id > 2) { Response.Write(d.ToString()   "<br/>"); } });

  能够看来,语句Lambda的侧面有二个语句块,在此个大括号内的言辞恐怕会有多条。

 

 

 

 

 

 标准查询运算符提供了席卷筛选、投影、聚合、排序等功能在内的查询成效,其本质是概念在System.Linq.Enumerable类中的50多个为IEnumerable<T>准备的扩大方法

时时app平台注册网站 47

  从上海体育场所能够看来,在Enumerable类中提供了重重的强盛方法,这里大家挑选个中多少个最常用的章程来作一点介绍,使我们能越来越好地运用它们。首先,大家供给或多或少数额来进展亲自去做:

时时app平台注册网站 48 View Code

无名函数

3.2 深入Predicate

  由于Predicate委托常用于在会集中寻找成分,那么大家就来走访哪些接受Predicate委托来扩充成分的查找。于是,大家将眼光转到List集结的FindAll方法,相信大多数童鞋都用过这几个方式。

  (1卡塔尔国先来看看FindAll的概念:

时时app平台注册网站 49)

                    //


                        // 摘要:

        //     检索与指定谓词定义的条件匹配的所有元素。


        //


                        // 参数:

        //   match:

        //     System.Predicate<T> 委托,用于定义要搜索的元素应满足的条件。


        //


                        // 返回结果:

        //     如果找到,则为一个 System.Collections.Generic.List<T>,其中包含与指定谓词所定义的条件相匹配的所有元素;否则为一个空


        //     System.Collections.Generic.List<T>。


        //


                        // 异常:

        //   System.ArgumentNullException:

        //     match 为 null。


                        public List<T> FindAll(Predicate<T> match);

时时app平台注册网站 50)

  (2卡塔 尔(英语:State of Qatar)再来看看FindAll的贯彻:

时时app平台注册网站 51

  (3卡塔尔国未来我们来用一下Predicate委托:照旧以十二分PersonList集合为例,假如大家要筛选出Age>20的Person,大家就足以行使FindAll方法。今后我们来写一下这一个委托:(前边大家会用拉姆da表达式来简写,那才叫贰个爽!卡塔尔国能够看来,关键点在于:delegate(Person p) { return p.Age > 20; }这一句上,传入参数是Person类型的靶子,重返的是多个相比结实即bool值。

时时app平台注册网站 52 View Code

Linq表达式用于离线集合的询问。什么是离线集结?最常用的是EF里面包车型大巴DBContext,作者也只用过这么些,所以我不想那么多,就把Expression当成EF里面使用的就能够了。

3.1 神奇—初玩扩充方法

  (1卡塔 尔(英语:State of Qatar)提到扩充方法,笔者想超过一半的园友都不目生了。可是还是来探视MSDN的概念:

MSDN 说:强盛方法令你能够向现存项目"添加"情势,而没有要求创造新的派生类型、重新编写翻译或以别的艺术修正原始类型。这里的"增加"之所以接纳引号,是因为并不曾真正地向内定项目丰硕方法。

  那么,临时候大家会问:缘何要有恢宏方法吧?此地,大家能够循名责实地想转手,扩展扩展,那么明确是关乎到可扩充性。在空虚工厂情势中,大家得以通过新增加叁个工厂类,而无需改进源代码就足以切换成新的厂子。这里也是如此,在不更改源码的情状下,为某些类增加新的秘诀,也就落实了类的扩大。

  (2卡塔尔空说无凭,大家来探视在C#中是怎么来判别扩大方法的:通过智能提醒,我们发掘成局地主意带了三个针对性下方的箭头,查看"温馨提示",大家通晓他是八个恢宏方法。所得是乃,原本大家直接对聚焦实行挑选的Where()办法依旧是扩展方法并非原生的。

时时app平台注册网站 53

  我们再来看看使用Where那几个扩张方法的代码示例:

时时app平台注册网站 54)

                    static
                            void UseExtensionMethod()

        {

            List<Person> personList = new List<Person>()

            {

                    new Person(){ID=1,Name="Big Yellow",Age=10},

                    new Person(){ID=2,Name="Little White",Age=15},

                    new Person(){ID=3,Name="Middle Blue",Age=7}

            };

 

                        // 下面就使用了IEnumerable的扩展方法:Where


                    var datas = personList.Where(delegate(Person p)

            {

                    return p.Age >= 10;

            });

 

                    foreach (var data in datas)

            {

                Console.WriteLine("{0}-{1}-{2}", 

                    data.ID, data.Name, data.Age);

            }

        }

时时app平台注册网站 55)

  上述代码应用了Where扩张方法,找寻集结中Age>=10的数据产生新的数据集并出口:

时时app平台注册网站 56

  (3卡塔 尔(英语:State of Qatar)既然增添方法是为了对类进行扩展,那么大家可以还是不可以实行自定义扩充呢?答案是必得能够。大家先来看看扩充方法是怎么着的概念的,能够通过刚刚的IEnumerable接口中的Where方法定义来会见有何准绳:通过 转到定义 的措施,大家得以观望在System.Linq命名空间下,有堪当Enumerable的如此三个静态类,它的成员方法全部都以静态方法,并且每一个方法的大多数第大器晚成参数都是以this早先。于是,我们得以总括出,增添方法的五个因素是:静态类静态方法以及this关键字

                    public
                            static
                                    class Enumerable

    {

                    public
                            static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer);

    }

  那么难点又来了:为什么一定得是static静态的吧?这么些大家都精晓静态方法是不归属某些类的实例的,也便是说大家不须要实例化那些类,就可以访谈那么些静态方法。所以,你懂的啦。

  (4卡塔 尔(英语:State of Qatar)看完扩大方法三要素,我们就来机关出手写三个扩张方法:

时时app平台注册网站 57)

                    public
                            static
                                    class PersonExtension

    {

                    public
                            static
                                    string FormatOutput(this Person p)

        {

                    return
                            string.Format("ID:{0},Name:{1},Age:{2}",

                p.ID, p.Name, p.Age);

        }

    }

时时app平台注册网站 58)

  上面那些扩充方法成功了叁个格式化输出Person对象属性音信的字符串构造,能够完毕地方例子中的输出效果。于是,我们得以将上边的代码改为以下的诀窍张开输出:

时时app平台注册网站 59)

                    static
                            void UseMyExtensionMethod()

        {

            List<Person> personList = new List<Person>()

            {

                    new Person(){ID=1,Name="Big Yellow",Age=10},

                    new Person(){ID=2,Name="Little White",Age=15},

                    new Person(){ID=3,Name="Middle Blue",Age=7}

            };

 

                    var datas = personList.Where(delegate(Person p)

            {

                    return p.Age >= 10;

            });

 

                    foreach (var data in datas)

            {

                Console.WriteLine(data.FormatOutput());

            }

        }

时时app平台注册网站 60)

2、拉姆da表达式只好有一条语句。

  2.1.1 未有Func时的使用

时时app平台注册网站 61 View Code

 

二、佚名方式:[ C# 2.0/.NET 2.0 新扩大特色 ]

然则只要本身只想把这段代码片使用二遍啊?再声称二个类、多个方法其实太麻烦,当时无名氏函数就具有了股票总值。用来封装意气风发段代码、间接试行或许传递。

四、再次回到int类型的内置委托—Comparison

// 声明一个委托,类型是myDelegate,
public delegate void myDelegate(string str); 
public static void HellowChinese(string strChinese) 
{ 
    Console.WriteLine("Good morning,"   strChinese); 
    Console.ReadLine(); 
} 
// 实例化   
myDelegate d = new myDelegate(HellowChinese); 
// 使用
d("Mr wang");

1.4 连接道士Join方法

  在数据库中,大家对七个表或三个表实行连接查询时一再会用到join语句,然后钦定多少个表之间的涉嫌关系(比如: a.bid = b.aid卡塔 尔(英语:State of Qatar)。在标准查询运算符中,留意的.NET基类库也为大家提供了Join方法。今后,若是我们有五个类:Person和Children,个中各个Children对象都有三个ParentID,对应Person对象的ID,现要求打字与印刷出全部Person和Children的音信,能够信任Join方法来贯彻。

时时app平台注册网站 62)

                    static
                            void SQOJoinDemo()

        {

            List<Person> personList = GetPersonList();

            List<Children> childrenList = GetChildrenList();

 

                        // 连接查询


                    var joinedList = personList.Join(childrenList,

                p => p.ID, c => c.ParentID, (p, c) => new


                {

                    ParentID = p.ID,

                    ChildID = c.ChildID,

                    ParentName = p.Name,

                    ChildName = c.ChildName

                }).ToList();

            joinedList.ForEach(c => Console.WriteLine(c.ToString()));

        }

时时app平台注册网站 63)

  运转结果如下图所示:

时时app平台注册网站 64

Expression指的是System.Linq.Expressions,是Linq表达式,表明式树,不是Lambda表明式!!

2.3 LINQ本质:生成对应的正经查询运算符

  作为七个缜密的.Net码农,大家不由自己作主对LINQ表明式为大家做了哪些工作而诡异?于是,大家又想起了大家的"滑登山鞋"—Reflector或ILSpy,去看看编写翻译器为大家做了怎么事!

  (1卡塔尔国以上述的主导法规查询代码为例,大家看出原本编写翻译器将LINQ生成了对应的专门的职业查询运算符,即Where扩张方法:

时时app平台注册网站 65

  (2卡塔尔国再来看看排序条件查询的代码,也是生成了对应的正式查询运算符,即OrderBy扩张方法:

时时app平台注册网站 66

  (3)总结:LINQ编写翻译后会生成对应的标准查询运算符(查询->Where,排序->OrderBy,连接->Join,分组->GroupBy卡塔 尔(英语:State of Qatar),所以LINQ表明式其实正是周边于SQL风格的风度翩翩种更加的温馨语法糖而已。其本质还是扩张方法、泛型委托等"旧酒",被二个"新转心瓶"所包装了起来,就变得高大上了。

Lamda表明式基本写法是()=>{ };
拉姆da和措施生龙活虎致都得以流传参数和富有再次回到值。(int x卡塔尔=>{return x;};
拉姆da表达式并不是C#独有的,此外语言也兼具Lambda表明式。

2.1 初识Func

MSDN提交的定义:打包多个具备二个参数并回到 TResult 参数钦点的类型值的章程

  此委托的概念如下:

public
                            delegate TResult Func<in T, out TResult>(T arg)

  (1卡塔尔in T :此委托封装的方法的参数类型。

  (2卡塔 尔(阿拉伯语:قطر‎out TResult :此委托封装的点子的回到值类型。

  能够动用此委托代表风度翩翩种能以参数格局传递的不二等秘书籍,而不用显式注脚自定义委托。封装的方式必得与此委托定义的方法具名相对应。也正是说,封装的法子必得怀有叁个透过值传递给它的参数,况且必需再次来到值。

        public delegate void Seep();
        static void Main(string[] args)
        {

            Seep s = () => { Console.WriteLine(2); Console.WriteLine(1); };
        }

1.1 筛选高手Where方法

  Where方法提供了大家对于四个集结的挑选功效,但须求提供多个带bool重返值的"筛选器"(无名情势、委托、拉姆da表明式均可卡塔 尔(阿拉伯语:قطر‎,进而评释集结中有个别成分是不是合宜被重返。这里,大家以地点的数目为例,挑选出集合中保有性别为男,年龄抢先20岁的子群集,依附Where方法落成如下:

时时app平台注册网站 67)

                    static
                            void SQOWhereDemo()

        {

            List<Person> personList = GetPersonList();

 

            List<Person> maleList = personList.Where(p =>

                p.Gender == true && p.Age > 20).ToList();

            maleList.ForEach(m => Console.WriteLine(m.ToString()));

        }

时时app平台注册网站 68)

  (1卡塔尔运营结果如下图所示:

时时app平台注册网站 69

  (2卡塔 尔(阿拉伯语:قطر‎由本系列作品的第二篇可以知道,扩大方法的庐山面目目是在运维时调用扩大类的静态方法,而笔者辈写的Lambda表明式在编写翻译时又会被转为匿有名的模特式(正确地说应该是预约义泛型委托实例卡塔 尔(阿拉伯语:قطر‎作为艺术参数字传送入增添方法中,最终调用推行该扩张方法生成三个新的List集结重返。

            #region 无参数无返回值
            // lambda实现委托实例
            Action a1 = () => Console.WriteLine(1);
            a1();
            // delegate实现委托实例,下面不再演示delegate。
            Action a2 = delegate { Console.WriteLine(1); };
            a2();
            #endregion

            #region 有参数无返回值
            Action<int> a3 = (x) => Console.WriteLine(x);
            a3(1);
            #endregion

            #region 无参数有返回值的情况
            Func<int> e1= ()=> 1;
            var value1= e1();
            #endregion

            #region 有参数有返回值的情况
            // 最后一个泛型是返回值的类型
            Func<int,int> e2 = (x) => x 1;
            int value2= e2(1);
            // 多参数情况
            Func<int, int,int> e3 = (x,x2) => x x2   1;
            int value3 = e3(1,2);
            #endregion

            #region 返回值是布尔类型
            // 其实Predicate可以用Func返回值是bool来代替的。
            Predicate<int> p = (x) => x > 0;
            bool value4 = p(1);
            #endregion

2.2 LINQ使用:达成除Skip和Take外的正规化查询运算符的职能

  (1卡塔尔基本规范查询:

时时app平台注册网站 70

时时app平台注册网站 71)

            List<Person> personList = GetPersonList();

            List<Children> childList = GetChildrenList();

                        // 基本条件查询


            Console.WriteLine("Basic Query:");

                    var maleList = from p in personList

                    where p.Gender == true


                    select p;

            maleList.ToList().ForEach(m =>

                Console.WriteLine(m.ToString()));

时时app平台注册网站 72)

  (2卡塔 尔(英语:State of Qatar)排序条件查询:

时时app平台注册网站 73

时时app平台注册网站 74)

                        // 排序条件查询


            Console.WriteLine("Order Query:");

                    var orderedList = from p in personList

                    orderby p.Age descending

                    orderby p.Name ascending

                    select p;

            orderedList.ToList().ForEach(m =>

                Console.WriteLine(m.ToString()));

时时app平台注册网站 75)

  (3卡塔 尔(英语:State of Qatar)连接查询:

时时app平台注册网站 76

时时app平台注册网站 77)

                        // Join连接查询


            Console.WriteLine("Join Query:");

                    var joinedList = from p in personList

                             join c in childList

                             on p.ID equals c.ParentID

                    select
                            new


                             {

                                 Person = p,

                                 Child = c

                             };

                    foreach (var item in joinedList)

            {

                Console.WriteLine(item.ToString());

            }

时时app平台注册网站 78)

  (4卡塔尔分组查询:

时时app平台注册网站 79

时时app平台注册网站 80)

                        // 分组条件查询


            Console.WriteLine("Group Query:");

                    var groupList = from p in personList

                            group p by p.Gender;

                    foreach (var group in groupList)

            {

                Console.WriteLine("Group:{0}", 

                    group.Key? "男":"女");

                    foreach(var item in group)

                {

                    Console.WriteLine(item.ToString());

                }

            }

时时app平台注册网站 81)

  运维结果请参见上后生可畏节规范查询运算符中相关的运行结果,或下载附属类小构件运维查看,这里不再贴图。

微软直接就在框架中概念了二种委托:Action、Func、Predicate。这二种委托是C#的System命名空间中早已定义好的,如Action

1.7 浅谈延迟加载与那个时候加载

  (1)推迟加载(Lazy Loading卡塔 尔(英语:State of Qatar):唯有在大家亟需多少的时候才去数据库读取加载它。

  在正式查询运算符中,Where方法正是一个超人的推移加载案例。在实际上的付出中,我们反复会使用一些ORM框架举例EF去操作数据库,Where方法的施用则是每一次调用都只是在持续生成SQL语句时扩展二个询问条件,EF不可能明确此次查询是还是不是业已增加截至,所以并未有艺术木有办法在各种Where方法实践的时候鲜明最终的SQL语句,只可以回到一个DbQuery对象,当使用到那么些DbQuery对象的时候,才会依赖全部条件转移最后的SQL语句去查询数据库。

    var searchResult = personList.Where(p =>

          p.Gender == false).Where(p => p.Age > 20)

          .Where(p=>p.Name.Contains("奶茶"));

  (2)眼看加载(Eager Loading卡塔 尔(英语:State of Qatar):加载数据时就把该对象相关联的其它表的数量联手加载到内部存款和储蓄器对象中去。

  在正式查询运算符中,FindAll方法就是叁个天下无敌的即时加载案例。与延迟加载相对应,在付出中只要应用FindAll方法,EF会依照办法中的条件自动生成SQL语句,然后随时与数据库实行相互获取查询结果,并加载到内部存款和储蓄器中去。

                    var searchResult = personList.FindAll(p=>p.Gender == false


                && p.Name.Contains("奶茶"));

信托基本的运用富含扬言二个信托、实例化贰个信托、使用叁个寄托

2.3 无名氏情势扩展

  (1卡塔尔无名氏情势语法糖—越发简化你的代码

  在开拓中,大家往往会动用语法糖来写匿有名的模特式,比方上边所示:

        DelegateTest dgTest3 = delegate(string name)

        {

           Console.WriteLine("Goodbye,{0}", name);

        };

        dgTest3("Edison Chou");

  能够见见,使用该语法糖,将new DelegateTest()也去掉了。可知,编写翻译器让大家越来越轻易了。

  (2)传参也可以有大学问—向方法中传播佚名情势作为参数

  ①在支付中,大家再三注明了一个艺术,其参数是三个寄托对象,能够承担负何符合委托定义的方式。

                    static
                            void InvokeMethod(DelegateTest dg)

    {

         dg("Edison Chou");

    }

  ②大家可以将早就定义的主意地址作为参数传入InvokeMethod方法,举例:InvokeMethod(TestFunc); 当然,大家也得以应用佚名方式,无需独自定义就能够调用InvokeMethod方法。

    InvokeMethod(delegate(string name)

    {

          Console.WriteLine("Fuck,{0}", name);

    });

  (3卡塔尔国省略省略再省略—省略"大括号"

  经过编写翻译器的随地优化,大家发掘连delegate前面包车型地铁()都得以轻巧了,大家能够看看下边风流洒脱段代码:

    InvokeMethod(delegate { 

         Console.WriteLine("I love C sharp!"); 

    });

  而我们事先的定义是如此的:

                    public
                            delegate
                                    void DelegateTest(string testName);

 

                    static
                            void InvokeMethod(DelegateTest dg)

        {

            dg("Edison Chou");

        }

  大家开采定义时办法是内需传递三个string类型的参数的,不过大家简要了deletegate后边的括号之后就从未参数了,那么结果又是怎么着吧?经过调节和测量检验,发掘结果输出的是:I love C sharp!

  那时,大家就有一些百思莫解了!明明都不曾概念参数,为什么依旧满足了符合委托定义的参数条件吧?于是,大家带着主题素材或许依附Reflector去意气风发探毕竟。

  ①在Main函数中,能够看见编写翻译器为大家自行抬高了相符DelegateTest这些委托定义的方式参数,即一个string类型的字符串。即便,输出的是I love C sharp,但它真的是顺应章程定义的,因为它会承担多个string类型的参数,就算在方法体中从不应用到那些参数。

时时app平台注册网站 82

  ②正要在Main函数中看看了无名氏方式,现在得以看看编写翻译器为大家所生成的命名方式。

时时app平台注册网站 83

使用Lambda表达式:

二、查询情势什么人越来越快?LINQ:[ C# 3.0/.NET 3.x 新扩大特色 ]

注意

1、无名氏函数总是和寄托一同行使(二种预约义委托卡塔 尔(英语:State of Qatar)
2、使用三种预约义委托就足以满足大好些个供给。
3、Expression是Linq表达式树,只好使用选用一句lambda表达式。和无名氏函数非亲非故。

3.1 初识Predicate

  经过了Func的打听,大家得以明白接下去的那八个Predicate和Comparison其实都归于有再次来到值类型的嘱托,他们不过是五个实际的出格实例而已(叁个赶回bool类型,叁个回到int类型卡塔尔国。

MSDN交由的定义:表示定义一组条件并鲜明钦定对象是不是适合那些准则的点子

  它的概念非常粗略:(这里就不再对其开展表达了卡塔 尔(英语:State of Qatar)

public
                            delegate
                                    bool Predicate<in T>(T obj)

  此委托由 Array 和 List<T> 类的两种艺术应用,常用于在联谊中寻觅成分。

时时app平台注册网站 84

1.5 分组老师GroupBy方法

  在数据库中,我们要对查询结果实行分组会用到 group by 语句,在正规查询运算符中,大家也许有对应的GroupBy方法。这里,假如大家对Person数据集遵照性别举行分类,该怎么来写代码呢?

时时app平台注册网站 85)

                    static
                            void SQOGroupByDemo()

        {

            List<Person> personList = GetPersonList();

 

            IEnumerable<IGrouping<bool, Person>> groups =

                personList.GroupBy(p => p.Gender);

            IList<IGrouping<bool, Person>> groupList = groups.ToList();

 

                    foreach (IGrouping<bool, Person> group in groupList)

            {

                Console.WriteLine("Group:{0}", group.Key ? "男" : "女");

                    foreach (Person p in group)

                {

                    Console.WriteLine(p.ToString());

                }

            }

        }

时时app平台注册网站 86)

  (1卡塔尔国这里需要小心的是:通过GroupBy方法后回去的是一个IEnumerable<IGrouping<TKey, TSource>>项目,此中TKey是分组依靠的品种,这里是依附Gender来分组的,而Gender又是bool类型,所以TKey这里为bool类型。TSource则是分组之后相继要素的类别,这里是将List<Person>集结举办分组,因而分完组后每一个成分都存款和储蓄的是Person类型,所以TSource这里为Person类型,Do you understand now?

  (2卡塔尔运转结果如下图所示:

时时app平台注册网站 87

  (3卡塔 尔(阿拉伯语:قطر‎大概有人会说作者咋记得住GroupBy再次回到的老大类型,太长了,作者也不想记。怎么做吧?不怕,大家得以行使var关键字嘛:

时时app平台注册网站 88)

                    var annoyGroups = personList.GroupBy(p => p.Name).ToList();

                    foreach (var group in annoyGroups)

            {

                Console.WriteLine("Group:{0}", group.Key);

                    foreach (var p in group)

                {

                    Console.WriteLine(p.ToString());

                }

            }

时时app平台注册网站 89)

那三种委托的附和泛型情势,能够写出如下代码:

4.1 初识Comparison

MSDN交给的概念:意味着比较生机勃勃致档案的次序的八个目的的章程

  它的定义也极粗略:

public
                            delegate
                                    int Comparison<in T>(T x, T y)

  T是要比较的对象的类型,而重返值是一个有暗记整数,提醒 x 与 y 的绝对值,如下表所示:

含义

小于 0

x 小于 y。

0

x 等于 y。

大于 0

x 大于 y。

  此委托由 Array 类的 Sort<T>(T[], Comparison<T>) 方法重载和 List<T> 类的 Sort(Comparison<T>) 方法重载使用,用于对数组或列表中的成分实行排序

后生可畏对文书档案上写Lambda是佚名函数,小编认为是不对的,拉姆da能够象征一个无名函数,不过还足以来代表Linq表明式啊。

 

 

Lambda表达式

3.3 注意—总括扩大方法

  (1卡塔 尔(阿拉伯语:قطر‎怎么样定义扩大方法:

  定义静态类,并增添public的静态方法,第贰个参数 代表 增加方法的扩张类。

  a) 它必须放在叁个非嵌套、非泛型的静态类中(的静态方法);

  b) 它至少有一个参数;

  c) 第四个参数必得叠加 this 关键字;

  d) 第多少个参数无法有其余其余修饰符(out/ref卡塔 尔(阿拉伯语:قطر‎

  e) 首个参数不能够是指针类型

  (2卡塔 尔(英语:State of Qatar)当大家把增加方法定义到任何程序集中时,应当要在乎调用扩张方法的条件中须要富含扩大方法所在的*命名空间*!

  (3卡塔 尔(英语:State of Qatar)要是要触类旁通的类中自然就有和扩展方法的名称相像的措施,到底会调用成员方法依旧扩展方法吧?

答案:编写翻译器暗许以为四个表明式是要利用一个实例方法,但生龙活虎旦没有找到,就能够检讨导入的命名空间和脚下定名空间里富有的扩充方法,并同盟到相符的诀要。

1、只好采纳Lambda表达式表示的委托

2.1 从委托的申明聊起

  C#中的佚名格局是在C#2.0引进的,它截止了C#2.0以前版本注脚委托的当世无双格局是使用命名情势的时日。可是,这里大家依然看一下在尚未佚名格局以前,大家是怎么申明委托的。

  (1卡塔 尔(阿拉伯语:قطر‎首先定义贰个寄托项目:

public
                            delegate
                                    void DelegateTest(string testName);

  (2卡塔 尔(英语:State of Qatar)编写三个顺应委托规定的命名格局:

                    public
                            void TestFunc(string name)

        {

            Console.WriteLine("Hello,{0}", name);

        }

  (3卡塔尔国最后声圣元(Synutra卡塔 尔(阿拉伯语:قطر‎(Nutrilon卡塔尔国个委托实例:

    DelegateTest dgTest = new DelegateTest(TestFunc);

    dgTest("Edison Chou");

  (4卡塔尔国调节和测量试验运转能够赢得以下输出:

时时app平台注册网站 90

  由地点的步凑能够观望,我们要声多美滋个委托实例要为其编写一个切合规定的命名方式。不过,要是程序中这几个主意只被这么些委托行使的话,总会深感代码结构有一点点浪费。于是,微软引进了匿有名的模特式,使用匿有名的模特式注明委托,就能使代码结构变得简洁,也会省去实例化的后生可畏都部队分费用。

委托很好用。当编制程序到一定等第,开采只传递叁个或多少个int、strig类型参数是非常不足的,希望能够把后生可畏段代码进行传递来执行有个别操作,委托提供了这么的路径,寄托提供了黄金时代种能够直接待上访谈类中方法的门路,能够将艺术充当一个参数字传送递从而接收

三、再次来到bool类型的放到委托—Predicate

            Expression<Func<int,int>> eeee = (x)=> x  1 ;

4.2 深入Comparison

  由于Comparison委托常用来在集结中开展排序,那么大家就来拜见哪些行使Comparison委托来张开成分的排序。于是,大家将眼光转到List会集的Sort方法,相信半数以上童鞋也都用过那么些格局。

  (1卡塔尔国老惯例,依旧先看看Sort方法的定义:

时时app平台注册网站 91)

                    //


                        // 摘要:

        //     使用指定的 System.Comparison<T> 对整个 System.Collections.Generic.List<T> 中的元素进行排序。


        //


                        // 参数:

        //   comparison:

        //     比较元素时要使用的 System.Comparison<T>。


        //


                        // 异常:

        //   System.ArgumentNullException:

        //     comparison 为 null。


        //


                    //   System.ArgumentException:

        //     在排序过程中,comparison 的实现会导致错误。
                    例如,将某个项与其自身进行比较时,comparison 可能不返回 0。


                        public
                                void Sort(Comparison<T> comparison);

时时app平台注册网站 92)

  (2卡塔尔再来看看Sort方法的落到实处:

时时app平台注册网站 93

  能够观看,这里尽管接受Comparison委托但说起底仍然调换到了Comparer比较器,再度调用重载的Array.Sort静态方法举行排序。

时时app平台注册网站 94

  (3卡塔尔未来我们来用一下Comparison委托:还是以拾壹分PersonList集结为例,要是大家要以Age为标准举行降序排列,大家应当怎么来写这一个委托呢?

时时app平台注册网站 95 View Code

  达成的功力如下图所示:

时时app平台注册网站 96

  那么,假若是要进行升序排列呢?只要求改一下:return p2.Age-p1.Age; 改过一下被减数和减数的岗位,就能够到位升序和降序的切换。

时时app平台注册网站 97 View Code

时时app平台注册网站 98

应用委托

五、Lambda表达式:[ C# 3.0/.NET 3.x 新增加特色 ]

  回想,开掘上边的代码,供给传二个无名方法 ,写起来特别别扭。于是大家很想明白能无法有简化的语法呢?微软告诉我们:Of Course,必须有,它正是Lambda表明式。拉姆da表明式是比匿有名的模特式更简洁的风流罗曼蒂克种匿有名的模特式语法。

Lambda来源:1916年到1929年之间,科学家Alonzo Church等人表明了拉姆da积分。Lambda积分是用于表示函数的生机勃勃套系统,它使用希腊字母Lambda(λ卡塔 尔(英语:State of Qatar)来代表无名氏函数。近年来,函数式编制程序语言(如Lisp卡塔尔国使用那几个术语来代表能够一贯描述函数定义的表明式,表明式不再供给有名字了。

一、匿名类:[ C# 3.0/.NET 3.x 新扩展特色 ]

1.3 你到底有多少个Action可用?

时时app平台注册网站 99
  从图中得以观察,.NET Framework为大家提供了多达15个参数的Action委托定义,对于大面积的费用情况已经完全够用了。

  5.1.3 拉姆da本质探析

  (1卡塔尔以上述案例中的Sort方法为例:personList.Sort((p1, p2) => p1.Age - p2.Age);

  (2卡塔尔国通过反编写翻译工具,能够看来实际是宣称了一个Comparison委托实例:

时时app平台注册网站 100

  (3卡塔尔未来,大家来剖析一下切实的步凑:有了前头的根底,以后再来看就自在了不菲,So Easy!

    ①编写翻译器自动生成了二个Comparison委托:

时时app平台注册网站 101

    ②编写翻译器帮大家创立了二个切合Comparison委托签名的静态方法:

时时app平台注册网站 102

    ③实例化Comparison委托变量,并将艺术指针传入该信托;

    ④调用List<T>实例的Sort方法,并传播Comparison委托实例;

    当中,前边两步①和②足以透过反编写翻译后的C#代码获知,而前面两步③和④则供给经过IL代码来分析,前边早就介绍过相关,这里就不再赘言。

2.2 深入Func

5.1 初识Lambda表达式时时app平台注册网站 103  5.1.1 Lambda表明式要点

    ①Lambda表明式中的参数列表(参数数量、类型和岗位卡塔尔国必须与信托相相配

    ②表明式中的参数列表不确定须要包罗类型,除非委托有ref或out关键字(那时候必得出示申明卡塔尔;

    ③风华正茂经没有参数,必得运用风度翩翩组空的圆括号

5.2 回顾Lambda进化史

  前边了然了Lambda是何等,这里大家来回想一下Lambda的演化进度。时时app平台注册网站 104

  从演变进度能够清楚,编写翻译器在更为智能地帮大家做着越来越多的事情,而作者辈却在享用着编写翻译器带给的惠及沉浸在高效的付出成效中,变得尤为"懒"了。

1.6 分页实战Skip与Take方法

  相信广大人都选拔过正规查询运算符实行分页操作,这里大家再一次来拜谒怎样依靠Skip与Take方法来贯彻分页操作。照旧以PersonList集结为例,如果页面上的表格每页显示5条数据,该怎么来写代码呢?

时时app平台注册网站 105)

                    static
                            void SQOPagedDemo()

        {

                        // 这里假设每页5行数据


            // 第一页


            Console.WriteLine("First Page:");

                    var firstPageData = GetPagedListByIndex(1, 5);

            firstPageData.ForEach(d => Console.WriteLine(d.ToString()));

                        // 第二页


            Console.WriteLine("Second Page:");

                    var secondPageData = GetPagedListByIndex(2, 5);

            secondPageData.ForEach(d => Console.WriteLine(d.ToString()));

                        // 第三页


            Console.WriteLine("Third Page:");

                    var thirdPageData = GetPagedListByIndex(3, 5);

            thirdPageData.ForEach(d => Console.WriteLine(d.ToString()));

        }

 

                    static List<Person> GetPagedListByIndex(int pageIndex, int pageSize)

        {

            List<Person> dataList = GetMorePersonList();

                    return dataList.Skip((pageIndex - 1) * pageSize)

                .Take(pageSize).ToList();

        }

时时app平台注册网站 106)

  运转结果如下图所示:

时时app平台注册网站 107

1.2 投影大腕Select方法

  Select方法能够查询投射,再次来到新目的会集。这里,如若大家先筛选出全数男子集合,再根据男子集结中存有项的姓名生成子集结(这是叁个区别于原项指标类型卡塔尔,就可以依靠Select方法来达成。

时时app平台注册网站 108)

                    static
                            void SQOSelectDemo()

        {

            List<Person> personList = GetPersonList();

 

            List<LitePerson> liteList = personList.Where(p =>

                p.Gender == true).Select(

                p => new LitePerson() { Name = p.Name }).ToList();

            liteList.ForEach(p => Console.WriteLine(p.ToString()));

        }

时时app平台注册网站 109)

  (1卡塔 尔(阿拉伯语:قطر‎运营结果如下图所示:

时时app平台注册网站 110

  (2卡塔尔国这里也足以利用匿名类,能够节省事先表明LitePerson类的步凑,但需求匹配var使用:

var annoyList = personList.Where(p =>

    p.Gender == true).Select(

    p => new { Name = p.Name }).ToList();

  (3卡塔尔这里因为完成LitePerson类重写了ToString()方法,所以这里平昔调用了ToString()方法。

2.1 初识LINQ:相仿SQL风格的代码

  LINQ又称语言集成查询,它是C# 3.0的新语法。在更加多的人看来,它是意气风发种有益的查询表明式,只怕说是和SQL风格周边的代码

                    var maleList = from p in personList

                    where p.Gender == true


                        select p;

  (1卡塔 尔(英语:State of Qatar)LINQ表明式以"from"起始,以"select 或 group by子句"结尾;

  (2卡塔尔LINQ表明式的出口是二个IEnumerable<T> 或 IQueryable<T> 集结;(注:T 的档期的顺序 由 select 或 group by 揣摸出来卡塔尔国

3.2 嗦嘎—探秘扩张方法

  刚刚大家心得了扩充方法的玄妙之处,今后我们针对刨根究底的学习态度,依赖Reflector看看编译器到底帮大家做了怎么着工作?

  (1卡塔 尔(阿拉伯语:قطر‎通过反编写翻译刚刚那叁个UseMyExtensionMethod方法,大家开采并未怎么意外之处。

  (2卡塔尔那时,大家得以将C#切换来IL代码看看,只怕会有另黄金年代番拿走?于是,决断切换之后,开采了真理!

时时app平台注册网站 111

  原本编写翻译器在编写翻译时自动将Person.FormatOutput校订为了PersonExtension.FormatOutput,这个时候大家好像振聋发聩,所谓的扩大方法,原本正是静态方法的调用而已,所德是乃(原来那样卡塔 尔(阿拉伯语:قطر‎!于是,我们得以将那样感到:person.FormatOutput() 等同于调用 PersonExtension.FormatOutput(person);

  (3卡塔尔再查看所编写翻译生成的不二诀要,开掘this关键已经破灭了。我们禁不住一声感叹,原本this只是贰个标志而已,标识它是增添的是哪三个种类,在方法体中能够对这么些项目标实例进行操作。

时时app平台注册网站 112

1.2 深远匿名类背后

   既然我们开掘无名类能够完全达成签名类的功能,那么大家得以大胆推断编译器料定在在那之中帮大家调换了多少个近乎签名类的class,于是,大家依然依赖反编写翻译工具对其开展研商。通过Reflector反编写翻译,大家找到了编写翻译器生成的无名氏类如下图所示:

时时app平台注册网站 113

  从上海体育地方能够看出:

  (1卡塔尔国匿名类被编写翻译后会生成二个[泛型类],能够观察上海体育场所中的<>f__AnonymousType0<<ID>j__TPar, <Name>j__TPar, <Age>j__TPar>正是叁个泛型类;

  (2卡塔 尔(阿拉伯语:قطر‎无名类所生成的习性都以只读的,能够看到与其相应的字段也是只读的;

  时时app平台注册网站 114

  所以,假使大家在前后相继中为属性赋值,那么会晤世错误;

  时时app平台注册网站 115

  (3卡塔 尔(英语:State of Qatar)可以观望,无名氏类还重写了基类的八个方式:Equals,GetHashCode和ToString;大家能够看看它为大家所生成的ToString方法是怎么来落实的:

  时时app平台注册网站 116

  达成的成效如下图所示:

时时app平台注册网站 117

二、有重返类型的嵌入委托—Func

本文由时时app平台注册网站发布于编程知识,转载请注明出处:C#中匿名函数、委托delegate和Action、Func、Expressi

关键词: