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

C#中如何将派生类集合传入接收基类集合的方法?

问题原因分析

你遇到的编译错误核心是C#泛型集合的不变性:虽然Car和Plane都继承自Vehicle,但List<Car>并不是List<Vehicle>的子类——List<T>是**不变(invariant)**的泛型类型,它不支持将派生类集合直接赋值给基类集合的引用。

而IEnumerable<out T>是**协变(covariant)**的(注意out关键字),它允许将IEnumerable<Car>隐式转换为IEnumerable<Vehicle>,这也是我们解决问题的关键。


解决方案

我给你推荐三种简洁的解决方式,按推荐程度排序:

1. 将方法参数改为IEnumerable<Vehicle>

这是最省心的方案,因为你的方法只需要遍历集合,不需要修改集合(比如添加/删除元素),IEnumerable<T>完全能满足需求,同时它支持协变:

namespace Rextester {
    abstract class Vehicle{ 
        public int Speed; 
    }
    class Car: Vehicle{ 
        public string VIN; 
    }
    class Plane : Vehicle{ 
        public int altitude; 
    }

    public class Program {
        public static void Main(string[] args) {
            var cars= new List<Car>();
            var planes = new List<Plane>();
            
            List<Vehicle> movingCars= getMovingVehicles(cars);
            List<Vehicle> movingPlanes=getMovingVehicles(planes);
        }

        // 修改参数为IEnumerable<Vehicle>
        static List<Vehicle> getMovingVehicles(IEnumerable<Vehicle> vehicles){
            List<Vehicle> movingVehicles=new List<Vehicle>();
            foreach( Vehicle v in vehicles){
                if(v.Speed>0) 
                    movingVehicles.Add(v);
            }
            return movingVehicles;
        }
    }
}

2. 使用泛型方法(保留List参数,同时支持派生类)

如果你必须保留List<T>作为参数,可以写一个带泛型约束的方法,这样既能接收任意Vehicle派生类的List,还能灵活控制返回类型:

namespace Rextester {
    abstract class Vehicle{ 
        public int Speed; 
    }
    class Car: Vehicle{ 
        public string VIN; 
    }
    class Plane : Vehicle{ 
        public int altitude; 
    }

    public class Program {
        public static void Main(string[] args) {
            var cars= new List<Car>();
            var planes = new List<Plane>();
            
            // 可以返回List<Car>或者List<Vehicle>,按需选择
            List<Car> movingCars= getMovingVehicles(cars);
            List<Plane> movingPlanes=getMovingVehicles(planes);
            // 或者转成基类集合
            List<Vehicle> movingCarsAsVehicle= getMovingVehicles(cars);
        }

        // 泛型方法,约束T必须是Vehicle的子类
        static List<T> getMovingVehicles<T>(List<T> vehicles) where T : Vehicle{
            List<T> movingVehicles=new List<T>();
            foreach( T v in vehicles){
                if(v.Speed>0) 
                    movingVehicles.Add(v);
            }
            return movingVehicles;
        }
    }
}

这种方法的好处是返回的集合类型和输入一致,不需要额外的类型转换,更符合类型安全的要求。

3. 调用时显式转换(不推荐,仅作补充)

如果你不想修改原方法,也可以在调用时把List<Car>转成List<Vehicle>,但这种方式需要额外的转换操作,不够优雅:

// 在Main方法中修改调用代码
List<Vehicle> movingCars= getMovingVehicles(cars.Cast<Vehicle>().ToList());
List<Vehicle> movingPlanes=getMovingVehicles(planes.Cast<Vehicle>().ToList());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:33:16