我正在尝试使用c# 11 refstruct/fields来创建一个" reftuple ",这是一个类型,可以容纳多个ref
。
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);
}
}
我的想法是,我可以初始化并传递类型为RefTuple<T1, T2>
的对象到使用ref
的函数,然后该函数可以改变Item1
等,这将修改初始化RefValue
时使用的原始拒绝。
问题:
上面的
Equals(object o)
不编译似乎is
操作符不与重构一起工作?我不确定如何正确地实现它。Equals(object o)
还显示"参数'o'类型的可为空性与覆盖的成员不匹配";我无法解决这个问题(代码启用了空性)Equals(RefTuple<T1, T2> o)
正在使用object.Equals
,但我认为这可能效率不高,因为它可能最终会装箱。我尝试代替Item1.Equals(o.Item1) && Item2.Equals(o.Item2)
,但随后得到上面的空性警告。
-
使用
ref struct
时有一些限制,其中之一是:ref struct
不能装箱到System。ValueType或System.Object.Equals(object o)
中的参数o
永远不能是RefTuple
的类型,所以您可以简单地返回false。 -
这个方法在基类中的签名是:
bool Equals(object? obj)
被覆盖的方法需要匹配它。
public override bool Equals(object? o) => false;
-
即使你调用
Item1.Equals(o.Item1)
,你仍然调用Equals(object)
方法,装箱不能被忽略。内置的ValueTuple
类使用EqualityComparer<T1>.Default
,也许这是供参考的。public bool Equals(RefTuple<T1, T2> o) { return EqualityComparer<T1>.Default.Equals(Item1, o.Item1) && EqualityComparer<T2>.Default.Equals(Item2, o.Item2); }