I am trying to learn the Linq/Lambda expressions and was stuck at somewhere. 
What I was Doing
I have created two classes with properties which have some common properties in them. The classes are like(It's test code).
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;
        }
    }
Then I created the two list for them as,
        List<TestA> testListA = new List<TestA>();
        List<TestB> testListB = new List<TestB>();
        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);
Now for result I wanted t2 as it's ProductID match is not in the testListB 
And t4 as it has matching ProductID in testListB but don't have the same Category.
1) I need a List<A> of every record which: No longer has a ProductID held in the testListB
which I can get as ,
  testListA.Select(x => x.ProductID).Except(testListB.Select(x => x.ProductID ));
2)No longer has a record which has a matching ProductID and Category in testListB  
which I Can get using,
   testListA.Where(a => testListB.Any(b => a.ProductID == b.ProductID && a.Category != b.Category));
**My Question **
Is it possible two make single linq expression to get result.I thought of using the  implement IEqualityComparer but I am not sure how to implement the GetHashCode it for two different type of classes. So either combining the above query into single query or any other way to  impliment custom Comparer for two different Type of classes. Or is there any other simple way?
You have said that you need only these objects from testListA:
ProductID in testListB
ProductID, but with different Category
So, your filter must be:
!testListB.Any(b => a.ProductID == b.ProductID && a.Category == b.Category)
So, change your code as:
testListA.Where(a => !testListB.Any(b => a.ProductID == b.ProductID && a.Category == b.Category));
Second approach:
Or you can create a new List<TestA> from the second list:
 var secondListA = testListB.Select(x=> new TestA(){Category=x.Category, ProductID=x.ProductID}).ToList();
And then create your Comparer:
sealed class MyComparer : IEqualityComparer<TestA>
{
    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();
    }
}
And use Except() overload which produces the set difference of two sequences by using the specified IEqualityComparer<T> to compare values.:
var result = testListA.Except(secondListA, new MyComparer ()).ToList();
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With