There is a way without modifying the values, using unsafe code and the undocumented __makeref method:
public static void Main(string[] args)
{
object a = null;
object b = null;
Console.WriteLine(AreSame(ref a, ref b)); // prints False
Console.WriteLine(AreSame(ref a, ref a)); // prints True
}
static bool AreSame<T1, T2>(ref T1 a, ref T2 b)
{
TypedReference trA = __makeref(a);
TypedReference trB = __makeref(b);
unsafe
{
return *(IntPtr*)(&trA) == *(IntPtr*)(&trB);
}
}
Note: The expression *(IntPtr*)(&trA) relies on the fact that the first field of TypedReference is an IntPtr pointing to the variable we want to compare. Unfortunately (or fortunately?), there is no managed way to access that field — not even with reflection, since TypedReference can’t be boxed and, thus, can’t be used with FieldInfo.GetValue.