一个 有歧义 的 lambda 表达式
2009-11-11 21:22 鹤冲天 阅读(2738) 评论(27) 编辑 收藏 举报今天发现了一句有歧义的labmbda表达式,发出来供大家“把玩”。
先看引起“是非争端”的两个扩展方法:
1 public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
2 {
3 foreach (T t in source) action(t);
4 }
5
6 public static void ForEach<T>(this IEnumerable<T> source, Func<T, object> func)
7 {
8 foreach (T t in source) func(t);
9 }
2 {
3 foreach (T t in source) action(t);
4 }
5
6 public static void ForEach<T>(this IEnumerable<T> source, Func<T, object> func)
7 {
8 foreach (T t in source) func(t);
9 }
第一个ForEach扩展不用多说;第二个比较怪吧,其实没必要存在,我也想不起来之前为什么就写了这么一个扩展。
先别考虑第二个扩展的合理性,来看以下调用代码:
1 public class People
2 {
3 public string Name { get; set; }
4 public int Age { get; set; }
5 }
6
7 static public void Test()
8 {
9 People[] peoples = new People[]
10 {
11 new People { Name = "ldp615" },
12 new People { Name= "Tom" },
13 new People { Name ="Jim" }
14 };
15 peoples.ForEach(p => p.Age = 20);
16 }
2 {
3 public string Name { get; set; }
4 public int Age { get; set; }
5 }
6
7 static public void Test()
8 {
9 People[] peoples = new People[]
10 {
11 new People { Name = "ldp615" },
12 new People { Name= "Tom" },
13 new People { Name ="Jim" }
14 };
15 peoples.ForEach(p => p.Age = 20);
16 }
歧义在第15行,p => p.Age = 20。试问运行时会调用那个ForEach扩展呢??(先想想,答案在1楼)
两个ForEach,如果注释其中一个,代码同样能编译并运行,会自动匹配另外一个扩展。看来第15行有两重“含义”,如下:
1 peoples.ForEach(p => { p.Age = 20; });
2 peoples.ForEach(p => { return p.Age = 20; });
2 peoples.ForEach(p => { return p.Age = 20; });
以上两行代码中的lambda都可以简写成为 p => p.Age = 20,也就导致了歧义。
那么在编译时,如何确定使用那个含义呢?应该看应用的上下文:
- 两个ForEach只保留一个时:使用与上下文相匹配的那含义(比较好理解)。
- 两个ForEach都存在时:我就不清楚了,可能是随机选一个吧,或者有优先级之说?(哪位高手知道,给俺说声)
欢迎大家发表自己的看法。
-------------------
思想火花,照亮世界