I am trying to use C# 11 ref struct/fields to create a "ref tuple", that is a type that holds multiple refs.
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 theisoperator 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.Equalsbut 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 structcan't be boxed to System.ValueType or System.Object.The parameter
oinEquals(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-inValueTupleclass 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); }
