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

C#中能否构建泛型包装类型层次结构以实现参数兼容?

问题:让DoProcessing方法同时兼容ParentWrapper和DerivedWrapper类型

我创建了一个泛型包装类型AnimalVehicleWrapper,并实现了两个派生类型:ParentWrapper持有父类型Animal和Vehicle,DerivedWrapper持有更具体的派生类型Dog和Car。我希望DoProcessing方法在参数为ParentWrapper时,既能接受该类型,也能接受更具体的DerivedWrapper类型。

相关代码如下:

using Example;

namespace Example
{
    public class Animal
    {
        public string Name { get; set; }
    }

    public class Dog : Animal
    {
        int PawSize { get; set; }
    }


    public class Vehicle
    {
        public string Name { get; set; }
    }

    public class Car : Vehicle
    {
        public int TireCount { get; set; }
    }

    public class AnimalVehicleWrapper<T1, T2>
        where T1 : Animal
        where T2 : Vehicle
    {
        public virtual T1 AnimalOrDerived { get; set; }
        public virtual T2 VehicleOrDerived { get; set; }

    }
}

public class ParentWrapper : AnimalVehicleWrapper<Animal, Vehicle>
{

}

public class DerivedWrapper : AnimalVehicleWrapper<Dog, Car>
{

}

目标是让下面的方法既能接收ParentWrapper,也能接收DerivedWrapper:

public static void DoProcessing(ParentWrapper wrapper)
{
    // 希望这里能传入ParentWrapper或DerivedWrapper
}

解决方案

方案1:使用泛型方法

直接将DoProcessing定义为泛型方法,并添加与AnimalVehicleWrapper一致的类型约束,就能兼容所有符合约束的包装类型:

public static void DoProcessing<TAnimal, TVehicle>(AnimalVehicleWrapper<TAnimal, TVehicle> wrapper)
    where TAnimal : Animal
    where TVehicle : Vehicle
{
    // 你的处理逻辑
    // 例如读取 wrapper.AnimalOrDerived.Name
}

调用时编译器会自动推断类型,无需手动指定:

var parent = new ParentWrapper();
DoProcessing(parent);

var derived = new DerivedWrapper();
DoProcessing(derived);

方案2:通过协变接口实现

如果需要一个统一的基类型来接收不同的包装实例(比如存入同一个集合),可以定义协变泛型接口实现类型兼容:

  1. 先定义协变接口(注意使用out关键字,且只包含getter——协变类型参数只能用作输出):
namespace Example
{
    public interface IAnimalVehicleWrapper<out T1, out T2>
        where T1 : Animal
        where T2 : Vehicle
    {
        T1 AnimalOrDerived { get; }
        T2 VehicleOrDerived { get; }
    }
}
  1. 修改AnimalVehicleWrapper实现该接口:
public class AnimalVehicleWrapper<T1, T2> : IAnimalVehicleWrapper<T1, T2>
    where T1 : Animal
    where T2 : Vehicle
{
    public virtual T1 AnimalOrDerived { get; set; }
    public virtual T2 VehicleOrDerived { get; set; }
}
  1. 调整DoProcessing的参数类型为接口类型:
public static void DoProcessing(IAnimalVehicleWrapper<Animal, Vehicle> wrapper)
{
    // 处理逻辑,只能读取属性,不能修改(协变接口不支持setter输入操作)
}

此时ParentWrapper和DerivedWrapper都能传入该方法,因为协变允许IAnimalVehicleWrapper<Dog, Car>隐式转换为IAnimalVehicleWrapper<Animal, Vehicle>。

方案选择建议

  • 如果处理逻辑需要修改包装类的属性(调用setter),优先选泛型方法,协变接口不支持输入操作。
  • 如果需要统一类型管理不同包装实例,或希望方法参数语义更清晰,选协变接口方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 13:32:22