当前位置: 移动技术网 > IT编程>开发语言>c# > Lambda表达式

Lambda表达式

2019年09月18日  | 移动技术网IT编程  | 我要评论
lambda演变历史 .NetFramework1.0 1.1下,lambda表达式是这样去写的,首先声明一个无参无返回值delegate委托,再声明一个无参无返回值的方法,把这个方法当做参数一样传递给委托 你也可以声明一个有参数和有返回值的委托,就像声明方法一样: .NetFramework2.0 ...

lambda演变历史

  .netframework1.0  1.1下,lambda表达式是这样去写的,首先声明一个无参无返回值delegate委托,再声明一个无参无返回值的方法,把这个方法当做参数一样传递给委托

        public delegate void noreturnnopara();
        noreturnnopara method = new noreturnnopara(this.donothing);
        private void donothing()
        {
            console.writeline("this is donothing");
        }

  你也可以声明一个有参数和有返回值的委托,就像声明方法一样:

public delegate void noreturnwithpara(int x, string y);//1 声明委托
noreturnwithpara method = new noreturnwithpara(this.study);
        private void study(int id, string name)
        {
            console.writeline($"{id} {name} 学习.net高级班");
        }
//method.invoke(123, "strpram");
method(123,"strparm");//这两种调用方式是等效的

  .netframework2.0  匿名方法,delegate关键字,可以访问局部变量

                noreturnwithpara method = new noreturnwithpara(delegate (int id, string name)
                {
                    console.writeline(i);
                });
                method.invoke(234, "bingle");

  .netframework3.0   把delegate关键字去掉,增加了一个箭头goes to,lambda表达式  参数列表=>方法体

 noreturnwithpara method = new noreturnwithpara(
     (int id, string name) =>
 {
     console.writeline($"id:{id},name: {name}");
 });
 method.invoke(123, "bingle");

  省略参数类型,编译器的语法糖,虽然没写,编译时还是有的,根据委托推算

 noreturnwithpara method = new noreturnwithpara(
     (id, name) =>
     {
         console.writeline($"id:{id}name: {name}");
     });
 method.invoke(123, "bingle");

如果方法体只有一行,可以去掉大括号和分号

noreturnwithpara method = new noreturnwithpara(
    (id, name) => console.writeline($"id:{id},name: {name} "));
method.invoke(123, "bingle");

new noreturnwithpara可以省掉,也是语法糖,编译器自动加上

 noreturnwithpara method = (id, name) => console.writeline($"id:{id} ,name:{name}");
 method.invoke(123, "bingle"); 

lambda是什么?

  lambda只是实例化委托,是匿名方法,但是在编译的时候会分配一个名字,还会产生一个私有sealed类,这里增加一个刚发

lambda在多播委托

 noreturnwithpara method = new noreturnwithpara(this.study);
 method += this.study;
 method += (id, name) => console.writeline($"{id} {name}");

 method -= this.study;
 method -= (id, name) => console.writeline($"{id} {name} ");
 //多播委托里面的lambda无法移除, 不是2个实例,其实是2个不同的方法
 method.invoke(345, "bingle");

匿名方法或者lamdba表达式是不是只能是无返回值的?不是的,可以有返回值的。这里面的action和func是内置的委托

action action0 = () => { };
action<string> action1 = s => console.writeline(s); //参数只有一个  可以省略小括号
func<int> func0 = () => datetime.now.month;//如果方法体只有一行,去掉大括号分号return
int iresult = func0.invoke();

yield关键字:

  含有yield的函数说明它是一个生成器,而不是普通的函数。当程序运行到yield这一行时,该函数会返回值,并保存当前域的所有变量状态。

  等到该函数下一次被调用时,会从上一次中断的地方开始执行,一直遇到下一个yield,程序返回值,并在此保存当前状态;如此反复,知道函数正常执行完成。

  迭代器模式是设计模式中行为模式的一个例子,他是一种简化对象间通讯的模式,也是一种非常容易理解和使用的模式。

  简单来说,迭代器模式使得你能够获取到序列中的所有元素,而不用关心器类型是array,list,linked或者其他的什么序列结构。

  这一点使得能够非常搞笑的构建数据处理通道(data  pipeline),即数据能够进入处理通道,进行一系列的变换,活着过滤,然后得到结果。事实上,这正是linq的核心模式。

  在.net中,迭代器模式被ienumerator和ienumerable及其对应的泛型接口所封装。如果一个类实现了ienumerable接口,那么就能够被迭代。

  调用getenumerator方法将返回ienumerator接口的实现,它就是迭代器本身。迭代器类似数据库中的游标,它是数据序列中的一个位置记录。

  迭代器只能向前移动,同一个数据序列中跨域有多个迭代器同时对数据进行操作。

 

一个普通的获取数据的方法:

 public ienumerable<int> commonmethod()
 {
     list<int> results = new list<int>();
     int counter = 0;
     int result = 1;

     while (counter++ < 10)
     {
         thread.sleep(1000);
         console.writeline($"获取{counter}次数据");
         result = result * 2;
         results.add(result);
     }
     return results;
 }

yield获取数据:

 public ienumerable<int> yieldmethod()
 {
     int counter = 0;
     int result = 1;
     while (counter++ < 10)
     {
         thread.sleep(1000);
         console.writeline($"获取{counter}次数据");
         result = result * 2;
         yield return result;
     }
 }

这两个方法,可以通过调试看到他们之间的区别

这是普通方法获取数据的调试结果:

 

 这是yield方法调试获得的结果:

 

 

public ienumerable<int> createenumerable()
{
    try
    {
        console.writeline("{0} createenumerable()方法开始", datetime.now);
        for (int i = 0; i < 5; i++)
        {
            console.writeline("{0}开始 yield {1}", datetime.now, i);
            yield return i;
            console.writeline("{0}yield 结束", datetime.now);
            if (i == 4)
            {
                yield break;//直接终结迭代  4会出现的,,
            }
        }
        console.writeline("{0} yielding最后一个值", datetime.now);
        yield return -1;
        console.writeline("{0} createenumerable()方法结束", datetime.now);
    }
    finally
    {
        console.writeline("停止迭代!");
    }
}




ienumerable<int> iterable = new test().createenumerable();//1 不会直接执行
ienumerator<int> iterator = iterable.getenumerator();
console.writeline("开始迭代");
while (true)
{
    console.writeline("调用movenext方法……");
    boolean result = iterator.movenext();//2 正式开启createenumerable
    console.writeline("movenext方法返回的{0}", result);
    if (!result)
    {
        break;
    }
    console.writeline("获取当前值……");
    console.writeline("获取到的当前值为{0}", iterator.current);
}

 

这是调试获得的结果:

 

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网