Home > OS >  Creating a "ref tuple"
Creating a "ref tuple"

Time:01-16

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:

  1. Equals(object o) above does not compile seems the is operator does not work with ref structs ? I am not sure how to correctly implement it.

  2. 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)

  3. Equals(RefTuple<T1, T2> o) is using object.Equals but I believe that may not be efficient as it may end up boxing. I tried instead Item1.Equals(o.Item1) && Item2.Equals(o.Item2) but then get the nullability warnings above.

CodePudding user response:

  1. 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 in Equals(object o) can never be the type of RefTuple, so you can simply return false.

  2. 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;
    
  3. Even if you call Item1.Equals(o.Item1), you are still calling the method Equals(object), boxing cannot be ignored. The built-in ValueTuple class uses EqualityComparer<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);
    }
    
  • Related