I am trying to use C# 11 ref struct/fields to create a "ref tuple", that is a type that holds multiple ref
s.
ref struct RefTuple<T1, T2> {
public ref T1 Item1;
public ref T2 Item2;
public RefTuple(ref T1 item1, ref T2 item2)
{
Item1 = ref item1;
Item2 = ref item2;
}
public bool Equals(RefTuple<T1, T2> o) {
return Equals(Item1, o.Item1) && Equals(Item2, o.Item2);
}
public override bool Equals(object o) {
return o is RefTuple<T1, T2> rt && Equals(rt);
}
public override int GetHashCode() {
retrun HashCode.Combine(Item1?.GetHashCode() ?? 0, Item2?.GetHashCode() ?? 0);
}
public static bool operator ==(RefTuple<T1, T2> obj1, RefTuple<T1, T2> obj2) {
return obj1.Equals(obj2);
}
public static bool operator !=(RefTuple<T1, T2> obj1, RefTuple<T1, T2> obj2) {
return !obj1.Equals(obj2);
}
}
The idea is I can then initialize and pass an object of type RefTuple<T1, T2>
to a function using a ref
, and that function can then change Item1
etc which will modify the original ref used when initializing the RefValue
.
Problems:
Equals(object o)
above does not compile seems theis
operator does not work with ref structs ? I am not sure how to correctly implement it.Equals(object o)
also shows "Nullability of type of parameter 'o' doesn't match overridden member" which I am not able to resolve. (code has nullability enabled)Equals(RefTuple<T1, T2> o)
is usingobject.Equals
but I believe that may not be efficient as it may end up boxing. I tried insteadItem1.Equals(o.Item1) && Item2.Equals(o.Item2)
but then get the nullability warnings above.
CodePudding user response:
There's some limits when using a
ref struct
, one of them is:A
ref struct
can't be boxed to System.ValueType or System.Object.The parameter
o
inEquals(object o)
can never be the type ofRefTuple
, so you can simply return false.The signature of this method in the base class is:
bool Equals(object? obj)
The overridden method need match it.
public override bool Equals(object? o) => false;
Even if you call
Item1.Equals(o.Item1)
, you are still calling the methodEquals(object)
, boxing cannot be ignored. The built-inValueTuple
class usesEqualityComparer<T1>.Default
, maybe this is for reference.public bool Equals(RefTuple<T1, T2> o) { return EqualityComparer<T1>.Default.Equals(Item1, o.Item1) && EqualityComparer<T2>.Default.Equals(Item2, o.Item2); }