Created
January 15, 2014 20:55
-
-
Save VladimirReshetnikov/8444468 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
unsafe struct S | |
{ | |
public void* ptr; | |
public object obj; | |
static void Main() | |
{ | |
S s = default(S); | |
Console.WriteLine(Equals(s, s)); | |
} | |
} |
Interesting, why struct with only one pointer or with pointer and value type behaves correctly?
using System;
unsafe struct S_Ok1
{
public void* ptr;
public void* ptr2;
}
unsafe struct S_Ok2
{
public int n;
public int* ptr;
}
unsafe struct S
{
// Could be any reference type
public object o;
public int* ptr;
}
class Program
{
public static void Main()
{
S s = default(S);
S_Ok1 sOk1 = default(S_Ok1);
S_Ok2 sOk2 = default(S_Ok2);
Console.WriteLine(Equals(s, s)); // False
Console.WriteLine(Equals(sOk1, sOk1)); // True
Console.WriteLine(Equals(sOk2, sOk2)); // True
}
}
I assume that you ideas is correct, but in case when struct doesn't contains reference type fast version of Equals
method is used:
// Inside ValueType.cs
bool Equals(object obj)
{
//Compare type
object a = this;
if (CanCompareBits(this))
{
return FastEqualsCheck(a, obj);
}
//Compare using reflection
}
It seems that CanCompareBits
return true only when struct contains reference type but returns true if struct contains unsafe pointer, and this comment from Rotor is not accurate:
The comment of
CanCompareBits
says "Return true if the valuetype does not contain pointer and is tightly packed". And FastEqualsCheck uses "memcmp" to speed up the comparison.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
When commenting one of the fields, default
Equals
implementation uses byte-to-byte comparison.Otherwise, it walks over all the fields with reflection. Since pointer types are not
Object
-derived (to be exposed fromFieldInfo.GetValue()
), reflection API packs them into instances ofSystem.Reflection.Pointer
ref type. Unfortunately, this type do not overridesEquals()
implementation to provide value equality semantics.