Reputation: 14306
Recently I was wandering if it's possible to compare structs by reference. As reading a struct variable creates a copy of that variable, comparing standard structs by reference seems impossible. However using C# 7 ref
s would make more sense.
I defined 4 variables
MyStruct foo = new MyStruct(){SomeInt = 1};
ref MyStruct refFoo = ref foo;
MyStruct bar = new MyStruct() { SomeInt = 2 };
ref MyStruct refBar = ref foo;
struct MyStruct
{
public int SomeInt { get; set; }
}
When I try this: var comparison1 = ReferenceEquals(refFoo, refBar);
, I get warning saying that the value is always false, since I'm passing value types.
ref struct
insteadref struct MyStruct
{
public int SomeInt { get; set; }
}
When I try this: var comparison1 = ReferenceEquals(refFoo, refBar);
, I get a compilation error saying that MyStruct
is not assignable to parameter type object
. Same thing if I try: var comparison1 = ReferenceEquals(foo, bar);
MyStruct
is ref struct
, but refFoo
and refBar
variables are declared without ref
. (I get the same error as in the 2nd case)static void Main(string[] args)
{
MyStruct foo = new MyStruct(){SomeInt = 1};
MyStruct refFoo = foo;
MyStruct bar = new MyStruct() { SomeInt = 2 };
MyStruct refBar = foo;
var comparison1 = ReferenceEquals(refFoo, refBar);
}
ref struct MyStruct
{
public int SomeInt { get; set; }
}
Upvotes: 2
Views: 1094
Reputation: 2984
var comparison1 = ReferenceEquals(refFoo, refBar);
, I get warning saying that the value is always false, since I'm passing value types
Each of the values will boxed so the result is always false.
var comparison1 = ReferenceEquals(refFoo, refBar);
, I get a compilation error saying that MyStruct is not assignable to parameter type object. Same thing if I try:var comparison1 = ReferenceEquals(foo, bar);
ref
can't be boxed or unboxed (Like @PetSerAl wrote).
The last case is when MyStruct is ref struct, but refFoo and refBar variables are declared without ref. (I get the same error as in the 2nd case)
Same as above.
Bonus question: Why only the 2nd and 3rd examples give me a compilation error?
I'm sure now you understand.
So, is there some sneaky way to compare structs by reference?
If you mean comparing addresses, here are some examples:
class Program
{
struct Struct { public int Value { get; set; } }
ref struct RefStruct { public int Value { get; set; } }
static unsafe void Main(string[] args)
{
var @struct = new Struct { Value = 5 };
var struct2 = @struct;
ref Struct struct3 = ref @struct;
Struct* p = &@struct;
Struct* p2 = &struct2;
Console.WriteLine($"struct address is: {(int)p} struct value is {p->Value}");
Console.WriteLine($"struct2 address is: {(int)p2} struct2 value is {p2->Value}");
fixed (Struct* p3 = &struct3)
{
Console.WriteLine($"struct3 address is: {(int)p3} struct3 value is {p3->Value}");
}
Console.WriteLine();
Console.WriteLine($"struct and struct2 Unsafe.AreSame? {Unsafe.AreSame(ref @struct, ref struct2)}");
Console.WriteLine($"struct and struct3 Unsafe.AreSame? {Unsafe.AreSame(ref @struct, ref struct3)}");
Console.WriteLine();
var structAsPointer = Unsafe.AsPointer(ref @struct);
var struct2AsPointer = Unsafe.AsPointer(ref struct2);
var struct3AsPointer = Unsafe.AsPointer(ref struct3);
Console.WriteLine($"struct AsPointer and struct2 AsPointer are same? {structAsPointer == struct2AsPointer}");
Console.WriteLine($"struct AsPointer and struct3 AsPointer are same? {structAsPointer == struct3AsPointer}");
Console.WriteLine();
var refStruct = new RefStruct { Value = 7 };
var refStruct2 = refStruct;
RefStruct* p4 = &refStruct;
RefStruct* p5 = &refStruct2;
Console.WriteLine($"refStruct address is: {(int)p4}, refStruct value is: {p4->Value}");
Console.WriteLine($"refStruct2 address is: {(int)p5}, refStruct value is: {p5->Value}");
ref RefStruct refStruct3 = ref refStruct;
fixed (RefStruct* p6 = &refStruct3)
{
Console.WriteLine($"refStruct3 address is: {(int)p6}, refStruct3 value is: {p6->Value}");
Console.WriteLine();
Console.WriteLine($"refStruct and refStruct2 are same? {&refStruct == &refStruct2}");
Console.WriteLine($"refStruct and refStruct3 are same? {&refStruct == p6}");
}
}
}
Upvotes: 1