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 books = new List
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应该提供了这样的方法:

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没有这样的方法。

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

 1 Code highlighting produced by Actipro CodeHighlighter (freeware)
 2 http://www.CodeHighlighter.com/--> 1     //新增一个实现了IEqualityComparer接口的类
 3      public class BookComparer : IEqualityComparer
 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接口:

 1 Code highlighting produced by Actipro CodeHighlighter (freeware)
 2 http://www.CodeHighlighter.com/--> 1     public class KeyEqualityComparer : IEqualityComparer
 3     {
 4         private readonly Funcbool> comparer;
 5         private readonly Funcobject> keyExtractor;
 6 
 7         // Allows us to simply specify the key to compare with: y => y.ID
 8          public KeyEqualityComparer(Funcobject> keyExtractor) : this(keyExtractor, null) { }
 9 
10         // Allows us to tell if two objects are equal: (x, y) => y.Id == x.Id
11          public KeyEqualityComparer(Funcbool> comparer) : this(null, comparer) { }
12 
13         public KeyEqualityComparer(Funcobject> keyExtractor, Funcbool> 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(this IEnumerable list, T item, Funcobject> keyExtractor)
49         {
50             return list.Contains(item, new KeyEqualityComparer(keyExtractor));
51         }
52 
53         public static bool Contains(this IEnumerable list, T item, Funcbool> comparer)
54         {
55             return list.Contains(item, new KeyEqualityComparer(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 books = new List
 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 : IEqualityComparer
 48     {
 49         private readonly Funcbool> comparer;
 50         private readonly Funcobject> keyExtractor;
 51 
 52         // Allows us to simply specify the key to compare with: y => y.Id
 53         public KeyEqualityComparer(Funcobject> keyExtractor) : this(keyExtractor, null) { }
 54 
 55         // Allows us to tell if two objects are equal: (x, y) => y.Id == x.Id
 56         public KeyEqualityComparer(Funcbool> comparer) : this(null, comparer) { }
 57 
 58         public KeyEqualityComparer(Funcobject> keyExtractor, Funcbool> 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     /// 
 92     /// 扩展方法
 93     /// 
 94     public static class MyExtMethod
 95     {
 96         public static bool Contains(this IEnumerable list, T item, Funcobject> keyExtractor)
 97         {
 98             return list.Contains(item, new KeyEqualityComparer(keyExtractor));
 99         }
100 
101         public static bool Contains(this IEnumerable list, T item, Funcbool> comparer)
102         {
103             return list.Contains(item, new KeyEqualityComparer(comparer));
104         }
105     }
106 }
View Code

 

转载于:https://www.cnblogs.com/Andy-Blog/p/5070933.html

你可能感兴趣的:(Lambda表达式, 可以让我们的代码更优雅.)