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

为何C#泛型函数MyFunc未调用MyClass的自定义Equals方法?

为什么泛型方法未触发自定义的Equals重载?

代码场景

MyClass 定义

public class MyClass
{
    int MyProp { get; set; }

    public MyClass(int val)
    {
        MyProp = val;
    }

    public bool Equals(MyClass obj)
    {
        return MyProp == obj.MyProp;
    }
}

泛型函数定义

bool MyFunc<T>(T obj1, T obj2)
{
    return obj1.Equals(obj2);
}

调用代码

MyFunc(new MyClass(1), new MyClass(2))

核心原因

泛型方法MyFunc<T>里的T没有任何约束,编译时编译器只能将obj1视为object类型(所有C#类型的基类)。此时调用的Equals是object.Equals(object),而非你在MyClass中定义的Equals(MyClass)重载。

虽然运行时T被推断为MyClass,但泛型方法的方法绑定是编译时静态绑定的——编译器不会因为运行时的具体类型,改变编译阶段选定的方法版本。你的Equals(MyClass)只是重载,没有重写object.Equals(object),所以通过object引用调用时,只会触发基类的默认引用相等比较逻辑,不会走到你的自定义方法里。

修复方案

方案1:重写基类Equals并实现IEquatable(推荐)

这是C#中实现自定义相等逻辑的标准做法,既保证兼容性,又能避免不必要的装箱操作:

public class MyClass : IEquatable<MyClass>
{
    int MyProp { get; set; }

    public MyClass(int val)
    {
        MyProp = val;
    }

    // 重写object.Equals(object),统一相等判断入口
    public override bool Equals(object obj)
    {
        return Equals(obj as MyClass);
    }

    // 实现IEquatable<MyClass>的强类型Equals,避免装箱开销
    public bool Equals(MyClass obj)
    {
        if (obj is null)
            return false;
        return MyProp == obj.MyProp;
    }

    // 重写GetHashCode是重写Equals的强制规范,避免哈希表类容器出错
    public override int GetHashCode()
    {
        return MyProp.GetHashCode();
    }
}

修改后,无论通过object还是MyClass类型调用Equals,都会触发你的自定义相等逻辑,泛型方法里的调用自然也能正常工作。

方案2:给泛型方法添加类型约束

如果不想修改MyClass,可以给MyFunc<T>添加where T : MyClass约束,让编译器明确知道T是MyClass或其子类,从而直接绑定到MyClass.Equals(MyClass):

bool MyFunc<T>(T obj1, T obj2) where T : MyClass
{
    return obj1.Equals(obj2);
}

但这种方式局限性强,仅适用于MyClass及其子类场景,通用性远不如方案1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 21:50:27