具有特定类型的 List 上的 C# 扩展方法

标签 c# generics inheritance type-conversion extension-methods

我有以下2种扩展方法

namespace Services.Resources.Extensions
{
    public static class DataMapExtensions
    {
        public static T ToDTO<T>(this BaseModel model)
        {
            return Mapper.Map<T>(model);
        }

        public static List<T> ToDTO<T>(this List<BaseModel> models)
        {
            return Mapper.Map<List<T>>(models);
        }

    }
}

第一种方法非常有效。

//Note: FlightRoute inherits BaseModel
FlightRouteDTO foo = new FlightRoute().ToDTO<FlightRouteDTO>(); //This works!

不过,第二种方法好像不行。

List<FlightRouteDTO> bar = new List<FlightRoute>().ToDTO<FlightRouteDTO>(); //This doesn't work!

编译器在说

Error CS1929 'List< FlightRoute>' does not contain a definition for 'ToDTO' and the best extension method overload 'DataMapExtensions.ToDTO< FlightRouteDTO>(List< BaseModel>)' requires a receiver of type 'List< BaseModel>'

但是FlightRoute类型为 BaseModel .如果我更改 bar 的类型明确为 List<BaseModel> ...然后问题就消失了。

List<FlightRouteDTO> bar = new List<BaseModel>().ToDTO<FlightRouteDTO>(); //Why does it only work this way?

我是否漏掉了一些明显的东西?

最佳答案

这只是预期的行为:您正在尝试使用 List<FlightRoute>作为 List<BaseModel> , 但仅仅因为 FlitghtRoute继承自 BaseModel不会 List<FlitghtRoute>继承自 List<BaseModel> : 它们是完全不同的类型。

相反,您可以利用 Covariance 的使用,使用接口(interface)而不是具体类型。

通过将您的方法签名更改为以下内容,您会注意到不会生成编译器错误:

public static List<T> ToDTO<T>(this IEnumerable<BaseModel> models)
{
    return Mapper.Map<List<T>>(models);
}

那是因为 IEnumerable<T>是具有协变 类型参数的接口(interface)。通过查看 reference source , 你会注意到这个接口(interface)是用 out T 声明的作为通用类型参数,表示 T是协变的,当我们使用 IEnumerable<T> 时可以被任何继承的类型替换.

关于具有特定类型的 List 上的 C# 扩展方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50081181/

相关文章:

c# - 如何处理非 fatal error 情况

c# - 获取属性的支持字段名称

Objective-c 在 init 方法中使用父属性

oop - 如何在MATLAB中的基类构造函数中调用适当的子类构造函数

c# - 尝试以编程方式打开 PowerPoint 时出错

c# - 如何在 Azure Blob 流中启用搜索

C# - 在两个字符串之间查找字符串

c# - 序列化泛型类

java - 如何从实现接口(interface)的泛型类返回接口(interface)?

java - 编译器看不到main方法