zoukankan      html  css  js  c++  java
  • Lambda表达式, 可以让我们的代码更优雅.

    在C#中, 适当地使用Lambda表达式, 可以让我们的代码更优雅.

    通过lambda表达式, 我们可以很方便地创建一个delegate:

    下面两个语句是等价的

    1 Code highlighting produced by Actipro CodeHighlighter (freeware)
    2 http://www.CodeHighlighter.com/-->//using delegate syntax
    3 Func<int, int> f = delegate(int i) { return ++i; }; 
    4 
    5 //using lambda syntax
    6 Func<int, int> f = i => ++i;
    View Code

    假如我要对一个列表进行排序:

     1 Code highlighting produced by Actipro CodeHighlighter (freeware)
     2 http://www.CodeHighlighter.com/-->using System;
     3 using System.Collections.Generic;
     4 using System.Linq;
     5 using System.Text;
     6 
     7 namespace ConsoleApplication1
     8 {
     9     class Program
    10     {
    11         static void Main(string[] args)
    12         {
    13             List<Book> books = new List<Book>
    14             {
    15                 new Book
    16                 { 
    17                     Id=1, 
    18                     Title="Design Patterns", 
    19                     Authors= new List<string>{"Erich Gamma", "Richard Helm", "Ralph Johnson", "John Vlissides"}
    20                 },
    21 
    22                 new Book
    23                 { 
    24                     Id=2, 
    25                     Title="Refactoring", 
    26                     Authors = new List<string>{"Martin Fowler"}
    27                 }
    28             };
    29 
    30             books.Sort((x, y) => x.Authors.Count - y.Authors.Count); //以作者个数进行排序
    31         }
    32     }
    33 
    34     public class Book
    35     {
    36         public int Id { get; set; }
    37         public string Title { get; set; }
    38         public List<string> Authors { get; set; }
    39     }
    40 }
    View Code

    的确很方便吧!

    我猜想List<T>应该提供了这样的方法:

    1 Code highlighting produced by Actipro CodeHighlighter (freeware)
    2 http://www.CodeHighlighter.com/-->1 //判断是否存在Id==1的书
    3  bool has_book_with_id_equals_one = books.Contains(new Book { Id = 1 }, (x, y) => x.Id == y.Id);
    4 
    5  //判断是否存在Title=="REFACTORING"(不区分大小写)的书
    6  bool has_book_with_title_equals_refactoring_ignorecase = books.Contains(new Book { Title = "REFACTORING" }, x => x.Title.ToUpper());
    View Code

    不幸的是, List<T>没有这样的方法。

    按照传统的方法, 你可能会这样写:

     1 Code highlighting produced by Actipro CodeHighlighter (freeware)
     2 http://www.CodeHighlighter.com/--> 1     //新增一个实现了IEqualityComparer<Book>接口的类
     3      public class BookComparer : IEqualityComparer<Book>
     4     {
     5         public bool Equals(Book x, Book y)
     6         {
     7             return x.Id == y.Id;
     8         }
     9         public int GetHashCode(Book obj)
    10         {
    11             return obj.Id.GetHashCode();
    12         }
    13     }
    14  //然后再干我们的活
    15  bool has_book_with_id_equals_one = books.Contains(new Book { Id = 1 }, new BookComparer());
    View Code

    很无奈的选择, 但是没办法!

    幸运的是,我们可以自己动手扩展List<T>接口:

     1 Code highlighting produced by Actipro CodeHighlighter (freeware)
     2 http://www.CodeHighlighter.com/--> 1     public class KeyEqualityComparer<T> : IEqualityComparer<T>
     3     {
     4         private readonly Func<T, T, bool> comparer;
     5         private readonly Func<T, object> keyExtractor;
     6 
     7         // Allows us to simply specify the key to compare with: y => y.ID
     8          public KeyEqualityComparer(Func<T, object> keyExtractor) : this(keyExtractor, null) { }
     9 
    10         // Allows us to tell if two objects are equal: (x, y) => y.Id == x.Id
    11          public KeyEqualityComparer(Func<T, T, bool> comparer) : this(null, comparer) { }
    12 
    13         public KeyEqualityComparer(Func<T, object> keyExtractor, Func<T, T, bool> comparer)
    14         {
    15             this.keyExtractor = keyExtractor;
    16             this.comparer = comparer;
    17         }
    18 
    19         public bool Equals(T x, T y)
    20         {
    21             if (comparer != null)
    22                 return comparer(x, y);
    23             else
    24             {
    25                 var valX = keyExtractor(x);
    26                 if (valX is IEnumerable<object>) // The special case where we pass a list of keys
    27                      return ((IEnumerable<object>)valX).SequenceEqual((IEnumerable<object>)keyExtractor(y));
    28                 return valX.Equals(keyExtractor(y));
    29             }
    30         }
    31 
    32         public int GetHashCode(T obj)
    33         {
    34             if (keyExtractor == null)
    35                 return obj.ToString().ToLower().GetHashCode();
    36             else
    37             {
    38                 var val = keyExtractor(obj);
    39                 if (val is IEnumerable<object>) // The special case where we pass a list of keys
    40                      return (int)((IEnumerable<object>)val).Aggregate((x, y) => x.GetHashCode() ^ y.GetHashCode());
    41                 return val.GetHashCode();
    42             }
    43         }
    44     }
    45 
    46     public static class MyExtMethod
    47     {
    48         public static bool Contains<T>(this IEnumerable<T> list, T item, Func<T, object> keyExtractor)
    49         {
    50             return list.Contains(item, new KeyEqualityComparer<T>(keyExtractor));
    51         }
    52 
    53         public static bool Contains<T>(this IEnumerable<T> list, T item, Func<T, T, bool> comparer)
    54         {
    55             return list.Contains(item, new KeyEqualityComparer<T>(comparer));
    56         }
    57     }
    View Code

    注意到上面的代码不仅仅针对Book,而是任意类型T

    现在,我们就可以无拘无束地用我们的自己的扩展方法了(完整代码):

      1 Code highlighting produced by Actipro CodeHighlighter (freeware)
      2 http://www.CodeHighlighter.com/-->using System;
      3 using System.Collections.Generic;
      4 using System.Linq;
      5 using System.Text;
      6 
      7 namespace ConsoleApplication1
      8 {
      9     class Program
     10     {
     11         static void Main(string[] args)
     12         {
     13             List<Book> books = new List<Book>
     14             {
     15                 new Book
     16                 { 
     17                     Id=1, 
     18                     Title="Design Patterns", 
     19                     Authors= new List<string>{"Erich Gamma", "Richard Helm", "Ralph Johnson", "John Vlissides"}
     20                 },
     21 
     22                 new Book
     23                 { 
     24                     Id=2, 
     25                     Title="Refactoring", 
     26                     Authors = new List<string>{"Martin Fowler"}
     27                 }
     28             };
     29 
     30             books.Sort((x, y) => x.Authors.Count - y.Authors.Count);
     31 
     32             bool has_book_with_id_equals_one = books.Contains(new Book { Id = 1 }, (x, y) => x.Id == y.Id);
     33 
     34             bool has_book_with_title_equals_refactoring_ignorecase = books.Contains(new Book { Title = "REFACTORING" }, x => x.Title.ToUpper());
     35             
     36         }
     37     }
     38 
     39     public class Book
     40     {
     41         public int Id { get; set; }
     42         public string Title { get; set; }
     43         public List<string> Authors { get; set; }
     44     }
     45 
     46 
     47     public class KeyEqualityComparer<T> : IEqualityComparer<T>
     48     {
     49         private readonly Func<T, T, bool> comparer;
     50         private readonly Func<T, object> keyExtractor;
     51 
     52         // Allows us to simply specify the key to compare with: y => y.Id
     53         public KeyEqualityComparer(Func<T, object> keyExtractor) : this(keyExtractor, null) { }
     54 
     55         // Allows us to tell if two objects are equal: (x, y) => y.Id == x.Id
     56         public KeyEqualityComparer(Func<T, T, bool> comparer) : this(null, comparer) { }
     57 
     58         public KeyEqualityComparer(Func<T, object> keyExtractor, Func<T, T, bool> comparer)
     59         {
     60             this.keyExtractor = keyExtractor;
     61             this.comparer = comparer;
     62         }
     63 
     64         public bool Equals(T x, T y)
     65         {
     66             if (comparer != null)
     67                 return comparer(x, y);
     68             else
     69             {
     70                 var valX = keyExtractor(x);
     71                 if (valX is IEnumerable<object>) // The special case where we pass a list of keys
     72                     return ((IEnumerable<object>)valX).SequenceEqual((IEnumerable<object>)keyExtractor(y));
     73                 return valX.Equals(keyExtractor(y));
     74             }
     75         }
     76 
     77         public int GetHashCode(T obj)
     78         {
     79             if (keyExtractor == null)
     80                 return obj.ToString().ToLower().GetHashCode();
     81             else
     82             {
     83                 var val = keyExtractor(obj);
     84                 if (val is IEnumerable<object>) // The special case where we pass a list of keys
     85                     return (int)((IEnumerable<object>)val).Aggregate((x, y) => x.GetHashCode() ^ y.GetHashCode());
     86                 return val.GetHashCode();
     87             }
     88         }
     89     }
     90 
     91     /// <summary>
     92     /// 扩展方法
     93     /// </summary>
     94     public static class MyExtMethod
     95     {
     96         public static bool Contains<T>(this IEnumerable<T> list, T item, Func<T, object> keyExtractor)
     97         {
     98             return list.Contains(item, new KeyEqualityComparer<T>(keyExtractor));
     99         }
    100 
    101         public static bool Contains<T>(this IEnumerable<T> list, T item, Func<T, T, bool> comparer)
    102         {
    103             return list.Contains(item, new KeyEqualityComparer<T>(comparer));
    104         }
    105     }
    106 }
    View Code
  • 相关阅读:
    TouchAction实现连续滑动设置手势密码
    用命令方式启动、停止appium服务和app
    企业软件防火墙iptables
    磁盘分区
    docker-网络
    docker-镜像管理基础
    docker-简单操作
    docker-安装
    python-函数
    find一些常用参数的一些常用实例和一些具体用法和注意事项。
  • 原文地址:https://www.cnblogs.com/Andy-Blog/p/5070933.html
Copyright © 2011-2022 走看看