Reputation: 21
Since C# 7.2 it is possible to use the "ref" keyword on structs to create embedded references. How can I determine if two struct variables are pointing to the same reference? ReferenceEquals
always returns false
:
SampleCode:
struct MyStruct
{
public string Name { get; set; }
}
static void Main(string[] args)
{
MyStruct val1 = new MyStruct() { Name = "Value1" };
MyStruct val2 = new MyStruct() { Name = "Value2" };
MyStruct val4 = new MyStruct() { Name = "New name" };
ref var val3 = ref val1;
val1.Name = "New name";
Console.WriteLine("Val 1: " + val1.Name);
Console.WriteLine("Val 2: " + val2.Name);
Console.WriteLine("Val 3: " + val3.Name);
Console.WriteLine("Val3 eq Val1: " + val3.Equals(val1));
Console.WriteLine("Val3 eq Val2: " + val3.Equals(val2));
Console.WriteLine("Val3 eq Val4: " + val3.Equals(val4));
Console.WriteLine("Val3 ref eq Val1: " + object.ReferenceEquals(val3, val1));
Console.WriteLine("Val3 ref eq Val2: " + object.ReferenceEquals(val3, val2));
Console.ReadKey();
}
Output:
Val 1: New name
Val 2: Value2
Val 3: New name
Val3 eq Val1: True
Val3 eq Val2: False
Val3 eq Val4: True
Val3 ref eq Val1: False <--- This should return true
Val3 ref eq Val2: False
So how to check for same struct
references in C# 7?
Upvotes: 2
Views: 559
Reputation: 20843
Have a look at C# 7 Series, Part 9: ref structs
ref struct is the stack-only value type that:
Represents a sequential struct layout; Can be used stack-only. i.e. method parameters and local variables; Cannot be static or instance members of a class or normal struct; Cannot be method parameter of async methods or lambda expressions; Cannot be dynamic binding, boxing, unboxing, wrapping or converting.
(emphasis mine)
and he goes on to implement Equals
as
public ref struct MyRefStruct
{
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj) => throw new NotSupportedException();
// ...
}
with the justification
Please note, I have overridden the Equals, GetHashCode and ToString methods that are inherited from System.Object. Because boxing is not allowed for ref structs, you will have no way to call these two base methods.
Note also that Compile time enforcement of safety for ref-like types
A value of a ref struct type may not be boxed:
[...] No instance method declared in object or in System.ValueType but not overridden in a ref struct type may be called with a receiver of that ref struct type.
That is, while you might implement ref struct MyEmbeddedStruct { public override bool Equals(object obj) => true; }
you will only be able to call it through val3.Equals(/*...*/)
but not through object.ReferenceEquals()
. And you cannot provide the parameter obj
to Equals
because you would have to box the parameter.
Therefore the answer to your question is probably: There is no way you can determine if two (embedded) structs are pointing to the same reference. (And this question would not make any sense in the first place when you are dealing with two normal structs.)
Upvotes: 5