自定义在lambda中相交

我想知道使用lambda表达式是否可以解决这个问题:

List listOne = service.GetListOne(); List listTwo = service.GetListTwo(); List result = new List(); foreach(var one in listOne) { foreach(var two in listTwo) { if((one.Id == two.Id) && one.someKey != two.someKey) result.Add(one); } } 

你当然可以! 您可以使用Linq的Intersect扩展方法的这个重载 , 该方法采用IEqualityComparer ,如下所示:

 public class FooComparer : IEqualityComparer { public bool Equals(Foo x, Foo y) { return x.Id == y.Id && x.someKey != y.someKey; } public int GetHashCode(Foo x) { return x.Id.GetHashCode(); } } ... var comparer = new FooComparer(); List listOne = service.GetListOne(); List listTwo = service.GetListTwo(); List result = listOne.Intersect(listTwo, comparer).ToList(); 
 listOne.SelectMany(x=>listTwo.Where(y=>x.Id==y.Id && x.someKey != y.someKey)); 

你可以尝试:

 var result = listOne.Join(listTwo, (one) => one, (two) => two, (one, two) => one, new MyFooComparer()); 

MyFooComparer外观如下:

 class MyFooComparer : IEqualityComparer { public bool Equals(Foo x, Foo y) { return x.Id == y.Id && x.someKey != y.someKey; } public int GetHashCode(Foo obj) { return obj.Id.GetHashCode(); } } 

[UPDATE]

我很好奇Intersect vs. Join的性能,所以我在我的解决方案和@ pswg之间做了一个小的性能比较( listOnelistTwo各有10个项目):

 var comparer = new MyFooComparer(); var sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 100000; i++) { var result1 = listOne.Intersect(listTwo, comparer).ToList(); } Console.WriteLine("Intersect: {0}",sw.Elapsed); sw.Restart(); for (int i = 0; i < 100000; i++) { var result = listOne.Join(listTwo, (one) => one, (two) => two, (one, two) => one, comparer); } Console.WriteLine("Join: {0}", sw.Elapsed); 

输出:

 Intersect: 00:00:00.1441810 Join: 00:00:00.0037063 
 var result = from one in listOne join two in listTwo on one.Id equals two.Id where one.SomeKey != two.SomeKey select one; 

更新:似乎有些人觉得这没有回答这个问题,因为据说它不使用lambdas。 当然是,它只是使用友好的查询语法。

这是完全相同的代码,只是不太可读:

 var result = listOne.Join(listTwo, one => one.Id, two => two.Id, (one, two) => new { one, two }) .Where(p => p.one.someKey != p.two.someKey) .Select(p => p.one);