Search code examples
c#.netreflectionsystem.reflection

Why does integer '0' IEquatable.Equals return true against a null object when called through reflection but false when called on the integer?


Calling IEquatable.Equals from an integer 0 to test against a null object should return false but when using reflection it returns true. Given the following code, I would expect for iEquals and equals to return 'false', but the reflection code returns true, why? I am on C# 7.3 and .NET Framework 4.6.2:

int zero = 0;
object nullObj = null;
var iEquals = zero.GetType().GetInterface("IEquatable`1").GetMethod("Equals");
var reflectionEquals = iEquals.Invoke(zero, new[] { nullObj }); // true
var equals = ((IEquatable<int>)zero).Equals(nullObj); // false

Solution

  • From the MethodBase.Invoke docs:

    If a parameter of the reflected method is a value type, and the corresponding argument in parameters is null, the runtime passes a zero-initialized instance of the value type.

    For int zero-initialized instance is 0, hence True. Another example can be bool - for booleans zero-initialized instance is false so:

    object nullObj = null;
    bool zero = false;
    var m = zero.GetType().GetInterface("IEquatable`1").GetMethod("Equals");
    Console.WriteLine(m.Invoke(zero, new[]{nullObj})); // True
    

    Demo @sharplab.io