0

I try to obtain a except-wise list using Linq, that is, I want to subtract list of elements from another list if exists. But the following doesn't remove duplicates.

var simplifiedList = request.CountryExceptionRecords
                .Where(e => !request.CopyInitialCountryExceptionRecords
                        .Any(c =>
                                    c.PropString1 == e.PropString1
                                    && c.PropString2.Trim()  == e.PropString2.Trim()
                                    && c.PropString3 == e.PropString3));

Edit, adding .Distinct() to the final(after Where) works like a charm. But I don't understand why it works because the classes used by the Records(Lists) implement neither GetHash nor Equal method.

Hax
  • 133
  • 9

1 Answers1

0

Adding .Distinct() to the final(after Where) works like a charm. But I don't understand why it works because the classes used by the Records(Lists) implement neither GetHash nor Equal method.

It's because from Distinct not working with LINQ to Objects

The Distinct() method checks reference equality for reference types. This means it is looking for literally the same object duplicated, not different objects which contain the same values.

So let me show you in example:

foo testA = new foo() { PropString1 = "A", PropString2 = "A", PropString3 = "A" };
foo testB = new foo() { PropString1 = "B", PropString2 = "B", PropString3 = "B" };
foo testC = new foo() { PropString1 = "C", PropString2 = "C", PropString3 = "C" };

List<foo> CountryExceptionRecords = new List<foo>();
CountryExceptionRecords.Add(testA);
CountryExceptionRecords.Add(testB);
CountryExceptionRecords.Add(testC);
CountryExceptionRecords.Add(testC); //adding duplicate item

List<foo> CopyInitialCountryExceptionRecords = new List<foo>();
CopyInitialCountryExceptionRecords.Add(testA); //same object adding second list

var simplifiedList = CountryExceptionRecords
                        .Where(e => !CopyInitialCountryExceptionRecords
                                        .Any(c =>
                                            c.PropString1 == e.PropString1
                                            && c.PropString2.Trim() == e.PropString2.Trim()
                                            && c.PropString3 == e.PropString3)).Distinct().ToList();

In this case the simplifiedList count would be 2 since lists have the objects with same reference.

But on the other hand following example does not remove duplicates it's because they are not same object reference wheares the object has same values. In this case you need to use IEqualityComparer

List<foo> CountryExceptionRecords = new List<foo>();
CountryExceptionRecords.Add(new foo() { PropString1 = "A", PropString2 = "A", PropString3 = "A" });
CountryExceptionRecords.Add(new foo() { PropString1 = "B", PropString2 = "B", PropString3 = "B" });
CountryExceptionRecords.Add(new foo() { PropString1 = "C", PropString2 = "C", PropString3 = "C" });
CountryExceptionRecords.Add(new foo() { PropString1 = "C", PropString2 = "C", PropString3 = "C" });

List<foo> CopyInitialCountryExceptionRecords = new List<foo>();
//This is another object wheares the values are same
CopyInitialCountryExceptionRecords.Add(new foo() { PropString1 = "A", PropString2 = "A", PropString3 = "A" });

var simplifiedList = CountryExceptionRecords
                        .Where(e => !CopyInitialCountryExceptionRecords
                                        .Any(c =>
                                            c.PropString1 == e.PropString1
                                            && c.PropString2.Trim() == e.PropString2.Trim()
                                            && c.PropString3 == e.PropString3)).Distinct().ToList();
Selim Yildiz
  • 5,254
  • 6
  • 18
  • 28
  • @SelimYıldız You should go on to say provided that the type being used doesn't implement `IEquatable.Equals` method, it uses `Object.Equals` thereby checking the reference equality. Sadece bit tavsiye. – Soner from The Ottoman Empire Apr 14 '20 at 21:51