You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用C# 11 ref struct创建ref tuple遇到的编译与空值问题

解决C# 11 Ref Struct "Ref Tuple"的Equals实现问题

核心前提:ref struct无法被装箱——这是解决所有Equals相关问题的关键,任何object类型的参数都不可能是ref struct的实例(装箱操作会直接触发编译错误)。基于这个特性,针对性解决你的三个问题:

问题1:重载Equals(object o)无法编译,is运算符不适用于ref struct

因为ref struct无法装箱,传入object o的参数永远不可能是当前ref struct的实例,直接返回false即可,无需尝试类型转换:

public override bool Equals(object? o)
{
    // ref struct无法装箱,o不可能是当前类型实例
    return false;
}

问题2:启用空值检查后,参数空值性与重写成员不匹配

基类object的Equals方法签名是public virtual bool Equals(object? obj),重写时必须将参数声明为object? o(而非非空的object o),才能匹配基类的空值性声明,消除警告。

问题3:泛型Equals方法的装箱效率与空值警告问题

不要用object.Equals(会触发装箱),也不要直接调用Item1.Equals(o.Item1)(可能引发空值警告),改用**EqualityComparer<T>.Default.Equals**——它自动处理空值,且不会触发装箱:

public bool Equals(RefTuple<T1, T2> other)
{
    return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
         && EqualityComparer<T2>.Default.Equals(Item2, other.Item2);
}

完整RefTuple示例代码

public readonly ref struct RefTuple<T1, T2> : IEquatable<RefTuple<T1, T2>>
{
    public readonly ref T1 Item1;
    public readonly ref T2 Item2;

    public RefTuple(ref T1 item1, ref T2 item2)
    {
        Item1 = ref item1;
        Item2 = ref item2;
    }

    // 解决问题1、2的Equals(object?)实现
    public override bool Equals(object? o)
    {
        return false;
    }

    // 解决问题3的泛型Equals实现
    public bool Equals(RefTuple<T1, T2> other)
    {
        return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
             && EqualityComparer<T2>.Default.Equals(Item2, other.Item2);
    }

    // 配套GetHashCode实现(需与Equals逻辑一致)
    public override int GetHashCode()
    {
        return HashCode.Combine(EqualityComparer<T1>.Default.GetHashCode(Item1),
                                EqualityComparer<T2>.Default.GetHashCode(Item2));
    }

    // 可选:重载==和!=运算符
    public static bool operator ==(RefTuple<T1, T2> left, RefTuple<T1, T2> right)
    {
        return left.Equals(right);
    }

    public static bool operator !=(RefTuple<T1, T2> left, RefTuple<T1, T2> right)
    {
        return !left.Equals(right);
    }
}

额外说明

  • ref struct的GetHashCode实现同样要用EqualityComparer<T>.Default.GetHashCode,避免直接调用Item1.GetHashCode()可能引发的空引用异常。
  • 由于ref struct无法装箱,Equals(object?)永远不会被合法调用(尝试传递ref struct实例给object参数会直接编译报错),所以返回false完全合理。

内容的提问来源于stack exchange,提问作者kofifus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 04:55:28