Search code examples
c#variablesstructtypescomparison

Struct type comparison


Imagine I have an IEnumerable<T> where T is a struct type. For each element of the collection I want to check whether there is another element with the same value.

Firstly, I thought about something like this:

IEnumerable<T> collection = someInput;

foreach(var element in collection)
{
  try
  {
    collection.First(x => x == element &&
                          x.GetHashCode() =! element.GetHashCode());

    DoA(element);
  }
  catch
  {
    DoB(element);
  }
}

But then I found out that hashes are actually equal for structures having same values. Apparently, Object.ReferenceEquals(x, element) is not a way as well.

So, there are 2 questions:

  1. Is there an option to distinguish two different struct variables with the same values?
  2. Is there any other other ways to solve my problem?

Thanks


Solution

  • Is there an option to distinguish two different struct variables with the same values?

    No, structs are so called value types. They are only defined by their values and have no reference. If you want to distinguish two instances which have equal values you have to use a class instead of a struct. Classes are reference types and therefore are distinguishable even if they have equal values because they have different references.

    In this case however you also have their position in the collection which could be used to distinguish them (it's bascially also some kind of reference).

    Is there any other other ways to solve my problem?

    As noted above you may use the position. Here's a simple basic implementation without LINQ. You can certainly make a shorter one with LINQ.

        for (var i = 0; i < collection.Count; i++)
        {
            var foundEqual = false;
            for (var j = 0; j < collection.Count; j++)
            {
                if (j != i && collection[i] == collection[j])
                {
                    foundEqual = true;
                    break;
                }
            }
            
            if (foundEqual)
            {
                DoA(collection[i]);
            }
            else
            {
                DoB(collection[i]);
            }   
        }
    

    If your struct doesn't implement IEquatable yet you have to implement it to make the equality comparison work. Look here for an explanation and an example: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type

    You should never rely on GetHashCode() for equality comparison as an equal hash code does not guarantee that the compared objects are actually equal.