1

Imagine I have a generic method involving type T. In terms of usage, T will only ever be of type Nullable<long> or Nullable<Guid>.

Because T is Nullable, I can't impose the type constraint where T : IComparable<T> on the method.

Given this, what is the most performant way of determining equality between two variables of type T within the method?

I am currently passing in a lambda function like (x, y) => x == y .. but feel there must be a better way.

Pancake
  • 739
  • 1
  • 5
  • 20
  • 2
    There is an `INullable` interface in the framework, but it's not generic. Did you mean the `Nullable` structure, which is not an interface? – Jeroen Mostert Jul 24 '18 at 08:34
  • Thanks @JeroenMostert, I have corrected the question – Pancake Jul 24 '18 at 08:36
  • if you want to check just equality, try x.Equals(y) – sTrenat Jul 24 '18 at 08:44
  • I appreciate everyone's answers and comments. Note that my original question specifically asks for the "most performant way" of doing the comparison. If anyone can explain why their approach would outperform the other recommendations, I'd be eager to accept this information as the definitive answer. – Pancake Jul 27 '18 at 22:01

3 Answers3

2

If T is always a Nullable, you can pass the underlying type's parameter (instead of Nullable<T>), and then use Nullable.Compare to do the comparison:

public static void Method<T>(Nullable<T> n1, Nullable<T> n2)
    where T : struct
{
    int comparisonResult = Nullable.Compare(n1, n2);
    ...
}
vc 74
  • 37,131
  • 7
  • 73
  • 89
2

The Comparer<T>.Default should handle perfectly well nullable values. It does a check about Nullable<> here so it should handle it.

Note that IComparable<> is used if you want to know <, >, <=, >=, == (so the order between two elements). If you only want Equals then use IEquatable<> (and EqualityComparer<T>.Default).

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • Xanatos, are you saying the behavior of Comparer.Default is identical to Nullable.Compare() in my use case? – Pancake Jul 26 '18 at 02:38
  • @Pancake `Nullable.Compare()` internally removes the `Nullable<>` and then uses `Comparer.Default` (see [here](https://github.com/Microsoft/referencesource/blob/master/mscorlib/system/nullable.cs#L112)]. Still even the `Comparer.Default` can do it, through another route. So they are equivalent. – xanatos Jul 26 '18 at 06:21
0

Another way to implement - https://dotnetfiddle.net/EBjU54

Here: I created a proper nullable comparing logic in a separate class to check the equality of two nullable. Next, as the anwser of vc74, you pass the underlying type's parameter and use the NullableComparer to check.

public static bool Comparexxx<T>(this T? myValue, T? otherValue)
            where T : struct
            { 
                var comparer = new NullableComparer<T>();

                return comparer.Compare(myValue, otherValue) == 1;              
            } 

            public class NullableComparer<T> : IComparer<Nullable<T>>
                  where T : struct
            {

                 public int Compare(Nullable<T> x, Nullable<T> y)
                 {              
                    //Two nulls are equal
                    if (!x.HasValue && !y.HasValue)
                        return 1;

                    //Any object is greater than null
                    if (x.HasValue && !y.HasValue) 
                        return 0;

                    if (y.HasValue && !x.HasValue)
                        return 0;

                    //Otherwise compare the two values
                    return x.Value.Equals(y.Value) ? 1 : 0 ;
                 }

            }
    }

And calling

long? a = 10;           
long? b = 10;
var rs = a.Comparexxx<long>(b);
Antoine V
  • 6,998
  • 2
  • 11
  • 34
  • Thierry, does your implementation handle cases that would have undesired outcomes if simply using Nullable.Compare()? – Pancake Jul 26 '18 at 02:35
  • My answer is about to create a separate class to handle the check equality. You can upgrade it as your requirement. If you use Nullable.Compare() ,https://msdn.microsoft.com/en-us/library/dxxt7t2a(v=vs.110).aspx ,it returns an integer that indicates the relative values of the n1 and n2 parameters. Take the approach you want. – Antoine V Jul 26 '18 at 08:28