Comparison of structures for equality without boxing

I stumbled upon an extension method that applies to structs (SomeStruct) and returns a value equal to the default(SomeStruct) value default(SomeStruct) (when the constructor without parameters is called).

 public static bool IsDefault<T> (this T value) where T : struct { return (!EqualityComparer<T>.Default.Equals(value, default(T))); } 

This made me wonder if the structure was built. This is purely out of curiosity, as there are pros and cons to boxing / passing by value depending on the context.

Assumptions:

  • The first of the following methods is illegal because structures do not implicitly override the equality operators ==/!= .
  • The second “appears” to avoid boxing.
  • The third method should always insert the structure as it calls object.Equals(object o) .
  • The fourth one has both overloads available (object/T) , so I guess this will also avoid boxing. However, the target structure needs to implement the IEquatable<T> interface, which makes the helper extension method not very useful.

Options:

 public static bool IsDefault<T> (this T value) where T : struct { // Illegal since there is no way to know whether T implements the ==/!= operators. return (value == default(T)); } public static bool IsDefault<T> (this T value) where T : struct { return (!EqualityComparer<T>.Default.Equals(value, default(T))); } public static bool IsDefault<T> (this T value) where T : struct { return (value.Equals(default(T))); } public static bool IsDefault<T> (this T value) where T : struct, IEquatable<T> { return (value.Equals(default(T))); } 

This question concerns the confirmation of the above assumptions and, if I do not understand and / or something I do not understand.

+6
source share
1 answer
  • The first of the following methods is illegal because structures do not implicitly override the equality operators == /! =.

True

  1. The second “appears” to avoid boxing.

The signature of the called EqualityComparer<T>.Equals(T,T) method, which uses the T parameters for the parameters, so boxing is not required for the call.

The default mapping implementation checks if T IEquatable<T> , and if it uses a IEquatable<T>.Equals that uses IEquatable<T>.Equals , and the other uses a comparator for Object.Equals , so boxing can be applied inside if the structure is not IEquatable ( 'only if necessary').

  1. The third method should always insert a structure, since it calls the object. Elements (object o).

True

  1. The fourth one has both overloads (object / T), so I guess this will also avoid boxing. However, the target structure needs to implement the IEquatable interface, which makes the helper extension method not very useful.

Yes, it does not require boxing like this SO answer . This is the efficient code that you will get for the specific case of T : IEquatable from EqualityComparer<T>.Default .

+4
source

All Articles