Coming from this stackoverflow question, the equality of two pointers (e.g. int*) depends on the layout of the struct that declares said pointer. For example:
unsafe readonly struct S1
{
public readonly int A1, A2;
public readonly int* B;
public S1(int a1, int a2, int* b)
{
A1 = a1;
A2 = a2;
B = b;
}
}
int x = 10;
var a = new S1(1, 2, &x);
var b = new S1(1, 2, &x);
Equals(a, b) // true
Here, two instances are equal, because a and b are compared with memcmp (bitwise comparison) which means that the address that B holds is compared (meaning comparison by value).
However, the following code
unsafe readonly struct S2
{
public readonly int A1;
public readonly int* B;
public S1(int a1, int* b)
{
A1 = a1;
B = b;
}
}
int x = 10;
var a = new S2(1, &x);
Equals(a, b) // false
Equals(a, a) // false!
fails the equality test. This is because System.ValueType.CanCompareBits evaluates to false (probably because of memory padding, I couldn't verify, it's a compiler intrinsic) and ValueType falls back to comparing the structs via reflection. Getting the value of a pointer via reflection causes that pointer to be boxed into a System.Reflection.Pointer, which is a reference type that does not override Object.Equals. Therefore, S2.B is compared by reference equality, which always evaluates to false because the pointer has been boxed during reflection.
This has been tested on netcore 2.1, 3.0 and net 5.0.
It looks like System.Reflection.Pointer should override Equals and compare the addresses of the pointer (aka its value).
Coming from this stackoverflow question, the equality of two pointers (e.g.
int*) depends on the layout of the struct that declares said pointer. For example:Here, two instances are equal, because
aandbare compared withmemcmp(bitwise comparison) which means that the address thatBholds is compared (meaning comparison by value).However, the following code
fails the equality test. This is because
System.ValueType.CanCompareBitsevaluates to false (probably because of memory padding, I couldn't verify, it's a compiler intrinsic) andValueTypefalls back to comparing the structs via reflection. Getting the value of a pointer via reflection causes that pointer to be boxed into aSystem.Reflection.Pointer, which is a reference type that does not overrideObject.Equals. Therefore,S2.Bis compared by reference equality, which always evaluates tofalsebecause the pointer has been boxed during reflection.This has been tested on netcore 2.1, 3.0 and net 5.0.
It looks like
System.Reflection.Pointershould overrideEqualsand compare the addresses of the pointer (aka its value).