Lambda表达式

作者: 高调的小丑 | 来源:发表于2017-07-05 14:10 被阅读123次

    Lambda表达式简介:

    MSDN定义:Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数。

    介绍

    1.lambda表达式是匿名函数,只不过长得不太像而已,可以看成是进化版。
    2.lambda表达式是用来创建委托或者目录树的匿名函数

    使用场景:

    可以在需要委托值的任何地方(也就是在可以使用匿名方法的任何地方)使用这些表达式。


    Lambda表达式的演化.png

    我的理解:

    其实Lambda表达式就是匿名方法。
    其中使用Lambda表达式来创建委托实例,我们却没有指出创建的委托类型,其中编译器会帮助我们去推断委托类型,从而简化我们创建委托类型所需要的代码,从而更加简洁。
    所以Lambda表达式可以总结为——它是在匿名方法的基础上,再进一步地简化了创建委托实例所需要的代码。
    匿名方法可以简明的忽略参数,但Lambda表达式不具备这一特性。

    Button btn=new Button();
    Btn.Text=“click me”;
    Btn.Click+=delegate{console.WriteLine(“LogPlain”);};//忽略了我们经常使用的参数delegate(object sender,EventArgs e){…}
    

    Lambda表达式使用演示

    static void Main(string[] args)
    {
        // Lambda表达式的演变过程
        // 下面是C# 1中创建委托实例的代码
        Func<string, int> delegatetest1 = new Func<string, int>(Callbackmethod);          
        //                                  ↓
        // C# 2中用匿名方法来创建委托实例,此时就不需要额外定义回调方法Callbackmethod
        Func<string, int> delegatetest2 = delegate(string text)
        {
             return text.Length;
        };
        //                                  ↓
        // C# 3中使用Lambda表达式来创建委托实例
        Func<string, int> delegatetest3 = (string text) => text.Length;
        //                                 ↓
        // 如果Lambda表达式只需一个参数,并且那个参数可以隐式指定类型时,
        // 此时可以把圆括号也省略,简化为:
       Func<string, int> delegatetest = text => text.Length;
    
        // 调用委托
        Console.WriteLine("使用Lambda表达式返回字符串的长度为: " + delegatetest("learning hard"));
        Console.Read();
    }
    
    /// <summary>
    /// 回调方法
    /// 如果使用了Lambda表达式和匿名函数,此方法就不需要额外定义
    /// </summary>
    /// <param name="text"></param>
    /// <returns></returns>
    private static int Callbackmethod(string text)
    {
        return text.Length;
    }
    

    Lambda结合Action和Func的使用

    Action<string> action = (str) => Console.WriteLine("Task={0}, str={1}, Thread={2}", Task.CurrentId, str, Thread.CurrentThread.ManagedThreadId);
    
    Func<int, int> negate =(n) =>{
         Console.WriteLine("Task={0}, n={1}, Thread={2}", Task.CurrentId, n, Thread.CurrentThread.ManagedThreadId);
         return -n;
    };
    
    Task<int>.Factory.StartNew(() => negate(6))
                     .ContinueWith(f => action("x"))
                     .Wait();
    

    Lambda表达式的使用

    主要的是在Linq表达式的使用,以及对扩展方法上的运用等
    例如:

    List list=new List();
    list.Add(2);
    list.Add(3);
    list.Where(x=>x%2==0);
    where方法其实就是一个扩展方法
     public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
    

    总结

    1. 匿名函数不等于匿名方法,匿名函数包含了匿名方法和lambda表达式这两种概念。
      匿名函数:{匿名方法,lambda表达式}

    2.lambda作为表达式,可以被C#编译器转换为委托,也可以被编译器转换为表达式树,匿名方法只能转换为委托。
    两者的共通点是都能被编译器转换成为委托,lambda表达式能完成几乎所有匿名方法能完成的事。

    延伸

    Linq查询操作符

    string[] words = { "zero","one", "two", "three", "four" };
    int[] numbers = { 0, 1, 2, 3, 4 };
    

    1.聚合

    numbers.Sum();
    numbers.Average();
    numbers.Count();
    numbers.LongCount(x => x % 2 == 0);
    words.Min();
    words.Max();
    numbers.Aggregate((a, b) => (a + b));
    

    2.链接

    numbers.Concat(new[] { 2, 3, 4, 5, 6 });
    

    3.转换

    words.Cast<string>()  //遍历时遇到转换失败的地方,会抛出异常
    words.OfType<string>()
    numbers.ToArray();
    numbers.ToList();
    words.ToDictionary(w => w.Substring(0, 2));
    numbers.Concat(new[] { 2, 3, 4, 5, 6 });
    

    4.元素操作符

    words.ElementAt(2);
    words.ElementAtOrDefault(10);
    words.First();
    words.First(w => w.Length == 3);
    words.First(w => w.Length == 10); //异常:没有匹配的元素
    words.FirstOrDefault (w => w.Length == 10); //null
    words.Last(); //"four“
    words.Single(); //异常:不止一个元素
    words.SingleOrDefault(); //异常:不止一个元素
    words.Single(word => word.Length == 5); //“three“   返回唯一元素
    words.Single(word => word.Length == 10); //异常:没有匹配的元素
    words.SingleOrDefault(w => w.Length == 10); //null   返回唯一元素
    

    5.相等操作

    words.SequenceEqual(new[]{“ZERO”,“ONE”,“TWO”,“THREE”,“FOUR”},StringComparer.OrdinalIgnoreCase);
    

    6.生成

    numbers.DefaultIfEmpty(); //0, 1, 2, 3, 4
    Enumerable.Range(0, 100);
    Enumerable.Repeat(25, 2);//生成包含重复值的序列
    Enumerable.Empty<int>();//生成任意类型的空序列
    

    7.分组

    words.GroupBy(word => word.Length);
    

    8.连接

    words.Join(allStrings, name => name[0], color => allStrings[0],(name, color) => name + " - " + color);
    words.GroupJoin
    

    9.分部

    words.Take(2); //"zero", "one"
    words.Skip(2); //"two","three", "four"
    words.TakeWhile(word => word.Length <= 4); //"zero", "one", "two"
    words.SkipWhile(word => word.Length <= 4); //"three","four“
    

    10.投影

    words.Select(word => word.Length);// 4, 3, 3, 5, 4
    words.Select((word, index) => index.ToString() + ": " + word); //"0: zero", "1: one", "2: two","3: three", "4: four"
    words.SelectMany(word => word.ToCharArray());//'z', 'e', 'r', 'o', 'o', 'n', 'e', 't', 'w', 'o', 't','h', 'r', 'e', 'e', 'f', 'o', 'u', 'r'
    

    11.数量

    words.All(word => word.Length > 3); //false("one"和"two"的确包含3个字母)
    words.All(word => word.Length > 2); //true
    words.Any(); //true(序列不为空)
    words.Any(word => word.Length == 6); //false(没有6个字母的单词)
    words.Any(word => word.Length == 5); //true("three"满足这个条件)
    words.Contains("FOUR"); //false
    words.Contains("FOUR",StringComparer.OrdinalIgnoreCase); //true
    

    12.过滤

     words.Where(word => word.Length > 3); //"zero", "three", "four“
    

    13.基于集的操作符

    "abbc".Distinct(); //"a", "b", "c"
    "abbc".Intersect("cd"); //"c"
    "abbc".Union("cd");//"a", "b", "c", "d"
    "abbc".Except("cd"); //"a", "b"
    "cd".Except("abc"); //"d“
    

    14.排序

    words.OrderBy(word => word);
    words.Reverse();
    words.OrderByDescending(word => word.Length);
    

    有部分内容是摘抄的深入浅出C#,附上PDF下载。

    相关文章

      网友评论

        本文标题:Lambda表达式

        本文链接:https://www.haomeiwen.com/subject/sytqhxtx.html