如何使用具有不同类的多个属性的linq`Exce`?

我正在尝试学习Linq/Lambda表达式并被困在某个地方。

我在做什么

我创建了两个具有属性的类,这些属性具有一些共同的属性。 这些类就像(它的测试代码)。

 class TestA { public int Id { get; set; } public int ProductID { get; set; } public string Category { get; set; } public TestA(int id, int procid, string category) { this.Id = id; this.ProductID = procid; this.Category = category; } } class TestB { public int ProductID { get; set; } public string Category { get; set; } public TestB(int procid, string category) { this.ProductID = procid; this.Category = category; } } 

然后我为他们创建了两个列表,

  List testListA = new List(); List testListB = new List(); TestA t1 = new TestA(1, 254, "ProductA"); TestA t2 = new TestA(1, 236, "ProductA"); TestA t3 = new TestA(1, 215, "ProductB"); TestA t4 = new TestA(1, 175, "ProductB"); TestA t5 = new TestA(1, 175, "ProductC"); testListA.Add(t1); testListA.Add(t2); testListA.Add(t3); testListA.Add(t4); testListA.Add(t5); TestB tt1 = new TestB(254, "ProdcutA"); TestB tt2 = new TestB(215, "ProductB"); TestB tt3 = new TestB(175, "ProductC"); testListB.Add(tt3); testListB.Add(tt2); testListB.Add(tt1); 

现在结果我想要t2因为它的ProductID匹配不在testListBt4因为它在testListB匹配ProductID但没有相同的Category
1)我需要每个记录的List :不再在testListB中保存ProductID

我能得到的,

  testListA.Select(x => x.ProductID).Except(testListB.Select(x => x.ProductID )); 

2)不再有在testListB中具有匹配的ProductIDCategory的记录

我可以使用,

  testListA.Where(a => testListB.Any(b => a.ProductID == b.ProductID && a.Category != b.Category)); 

**我的问题 **
是否有可能两个单个linq表达式得到结果。我想使用工具IEqualityComparer但我不知道如何为两种不同类型的类实现GetHashCode 。 因此要么将上述查询组合成单个查询,要么以任何其他方式将自定义Comparer用于两种不同类型的类。 还是有其他简单的方法吗?

您已经说过只需要来自testListA这些对象:

  • testListB没有匹配的ProductID
  • 存在mathing ProductID ,但具有不同的Category

所以,你的filter必须是:

!testListB.Any(b => a.ProductID == b.ProductID && a.Category == b.Category)

因此,将代码更改为:

 testListA.Where(a => !testListB.Any(b => a.ProductID == b.ProductID && a.Category == b.Category)); 

第二种方法:

或者您可以从第二个列表创建一个新的List

  var secondListA = testListB.Select(x=> new TestA(){Category=x.Category, ProductID=x.ProductID}).ToList(); 

然后创建您的Comparer

 sealed class MyComparer : IEqualityComparer { public bool Equals(TestA x, TestA y) { if (x == null) return y == null; else if (y == null) return false; else return x.ProductID == y.ProductID && x.Category == y.Category; } public int GetHashCode(TestA obj) { return obj.ProductID.GetHashCode(); } } 

并使用Except()重载,它通过使用指定的IEqualityComparer来比较值来产生两个序列的集合差异:

 var result = testListA.Except(secondListA, new MyComparer ()).ToList(); 

这是实现IEqualityComparer的示例。 它应该作为一个概念用于您的目的:

 private class PKExclusiveComparer : IEqualityComparer where T : DataRow { public bool Equals(T x, T y) { bool result = true; foreach (DataColumn col in (x as DataRow).Table.Columns) { if (!(x as DataRow).Table.PrimaryKey.Contains(col)) { result &= x[col].Equals(y[col]); } } return result; } public int GetHashCode(T x) { string code = string.Empty; foreach (DataColumn col in (x as DataRow).Table.Columns) { if (!(x as DataRow).Table.PrimaryKey.Contains(col)) { code += x[col].ToString(); } } return code.GetHashCode(); } }