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

C#派生类隐藏方法在泛型方法中失效,单元测试失败原因咨询

泛型与非泛型方法返回结果不一致的原因解析
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTest1
{
    // 声明一些隐藏基类方法并实现接口的类
    public interface IGet
    {
        string Get();
    }

    public class GetA: IGet
    {
        public string Get()
        {
            return "a";
        }
    }

    public class GetB: GetA
    {
        public new string Get()
        {
            return "b";
        }
    }

    public static class GetUtil<T> where T : IGet
    {
        public static string Get(T aGetObject)
        {
            return aGetObject.Get();
        }
    }

    public static class GetAUtil
    {
        public static string Get(GetA aGetObject)
        {
            return aGetObject.Get();
        }
    }

    public static class GetBUtil
    {
        public static string Get(GetB aGetObject)
        {
            return aGetObject.Get();
        }
    }

    [TestClass]
    public class NewUnitTest
    {
        // 验证泛型与非泛型方法返回结果一致
        [TestMethod]
        public void TestGetInterfaceImplemetors()
        {
            var a = new GetA();
            var b = new GetB();
            Assert.AreEqual(GetAUtil.Get(a), GetUtil<GetA>.Get(a));
            Assert.AreEqual(GetBUtil.Get(b), GetUtil<GetB>.Get(b)); //此处测试失败,原因何在?
        }
    }
}

核心原因拆解

1. new关键字的本质:隐藏而非重写

GetB类里的public new string Get()只是隐藏了基类GetA的Get方法,不是重写。它的作用是:当变量的编译类型是GetB时,调用Get会触发这个新方法;但如果变量的编译类型是基类GetA或者接口IGet,调用的还是原来的基类实现。

2. 非泛型方法GetBUtil.Get(GetB)的执行逻辑

这个方法的参数是明确的GetB类型,编译器直接绑定到GetB类里用new定义的Get()方法,所以返回值是"b"。

3. 泛型方法GetUtil<GetB>.Get(T)的执行逻辑

泛型约束where T : IGet不仅是类型限制,还会影响编译器的方法绑定逻辑:

  • 编译器在处理aGetObject.Get()时,会优先依据接口IGet的定义来解析方法(因为约束保证了T必然实现IGet)。
  • GetB并没有显式重新实现IGet接口的Get方法,它只是用new隐藏了基类的方法。所以接口IGet的Get方法在GetB实例上,实际指向的还是继承自GetA的实现,最终返回"a"。

修复思路(可选)

如果想让泛型方法也返回"b",可以选以下任意一种方式:

  • 给GetA的Get方法加上virtual,GetB的Get方法改用override(真正的重写,支持多态);
  • 让GetB显式实现IGet接口的Get方法:
    public class GetB: GetA, IGet
    {
        string IGet.Get()
        {
            return "b";
        }
        public new string Get()
        {
            return "b";
        }
    }
    
  • 移除泛型方法的IGet约束,让编译器直接根据T的实际类型绑定方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 17:43:13