因为实在太懒了,很久没动笔,今天强迫自己写一个小短篇。
之前讨论过用SelectMany代替两重的foreach循环。今天我们看一下Join和foreach的关系。
首先是Join的定义
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>( this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector )
那么我们根据这个方法的定义的写具体的实现如下
public static IEnumerable<TResult> MyJoin<TOuter, TInner, TKey, TResult>( this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector ) { List<TResult> result = new List<TResult>(); foreach (var o in outer) { var outerKey = outerKeySelector(o); foreach (var i in inner) { var innerKey = innerKeySelector(i); if (outerKey.Equals(innerKey)) { result.Add(resultSelector(o, i)); } } } return result; }
使用场景如下,存在两个有关联的表映射的集合对象。期望对两张表中数据做一个SQL中Join的级联效果
List<Developer> developers = new List<Developer> { new Developer{ Name = "Leo1" , ProjectID =1 }, new Developer{ Name = "Leo2" , ProjectID =2 }, new Developer{ Name = "Leo3" , ProjectID =3 } }; List<Tester> testers = new List<Tester> { new Tester{ Name = "Echo1" , ProjectID=1}, new Tester{ Name = "Echo2" , ProjectID=1}, new Tester{ Name = "Echo3" , ProjectID=2}, new Tester{ Name = "Echo4" , ProjectID=2}, new Tester{ Name = "Echo5" , ProjectID=3}, new Tester{ Name = "Echo6" , ProjectID=3} }; var projects = developers.MyJoin(testers, d => d.ProjectID, t => t.ProjectID, (d, t) => new { d.ProjectID, Developer= d.Name, Tester = t.Name }); foreach (var p in projects) { Console.WriteLine(p.ProjectID); Console.WriteLine(p.Developer); Console.WriteLine(p.Tester); }
一个开发配两个个测试,是不是很开心啊,不过这只是个Sample,你们就死心吧……结果如下
很简单的小例子,至少Linq to objects层面还是比较简单的。
同时祝愿各位.NET的工程师们能够越来越专业。面对快50岁的Boss说“代码不重要,业务最重要,代码就是10个if else和8个if else的区别”的时候能够不再迷茫,心中有数。不要把优美的C#写成了堆砌if else和switch case的意大利面条。