0

I have read about Except here. I am still a bit confused. I am using .NET 4.8.

I have 7 different implementations of my custom interface IMyInterface. All these implementations are held in a List or IEnumerable. I am doing the following in many places of my project (pseudocode):

List<IMyInterface> myList = //some items
List<IMyInterface> anotherList = //some more items
var difference = myList.Except(anotherList);

I think I am getting some not correct results. Looking into the issue a bit it seems that .NET compares equality by if the two objects pointers are the same. In my case some of these elements that I will be comparing will be copies so the tra=ditional Equals will fail. I definitely need to create a custom comparer.

I created methods on all these implementations that override Equals(). Example:

public override bool Equals(object obj)
{
    if (obj is null or not Arc) return false;
    var testObj = (Arc)obj;
    if (Key.SequenceEqual(testObj.Key)) return true;
    return false;
}

I then set breakpoints in all the new Equals() methods to tell if that custom Equals() method is being used.

I know that Linq does not execute until the data is needed. If I allow a line like this to run:

var difference = myList.Except(anotherList);

and then check the value of the variable difference by hovering over it in break mode there are results but my breakpoints never get hit.

How do I tell with certainty what Except() is using in my environment to make the determination of equality on my custom objects?

Eric Snyder
  • 1,816
  • 3
  • 22
  • 46
  • 2
    `Except` uses a `HashSet`; make sure you override `GetHashCode`. Actually, if you ever override `Equals`, override `GetHashCode` too – Caius Jard Nov 11 '21 at 21:28
  • @CaiusJard - I don't see anywhere at [this link](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.except?view=netframework-4.8) where the documentation states that Except uses a HashSet. Can you please give me more details? – Eric Snyder Nov 11 '21 at 22:23
  • 1
    Check the source code for Enumerable at source.dot.net or github or refsource.ms - https://source.dot.net/#System.Linq/System/Linq/Except.cs,e289e6c98881b2b8,references - https://github.com/microsoft/referencesource/blob/5697c29004a34d80acdaf5742d7e699022c64ecd/System.Core/System/Linq/Enumerable.cs#L899 - https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,9c10b234c0932864 - Ctrl-F for ExceptIterator – Caius Jard Nov 11 '21 at 22:32
  • Your own link to the documentation specifically describes how to compare custom objects in the examples section. You didn't do what it tells you to do, or what is shown in the example. – Servy Nov 11 '21 at 23:22
  • 1
    @CaiusJard - Thanks for that! The things you learn. I'll bet there is a TON to learn from the .NET source code - not that it's perfect. I'll bet that some of that code has been reviewed to death and really sharpened up. I appreciate the pointer to that. – Eric Snyder Nov 12 '21 at 13:48

1 Answers1

1

To use an Except in case of comparing list of objects, those objects should implement IEquatable<T>. In Your case the T should be IMyInterface to be safe.

Alternatively you could use overload that takes the custom comparer that derives from IEqualityComparer<IMyInterface>.

More info can be found here.

quain
  • 861
  • 5
  • 18