繁体   English   中英

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

[英]C# Extension method on List with specific type

我有以下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!

编译器说

错误CS1929'List <FlightRoute>'不包含'ToDTO'的定义,并且最佳扩展方法重载'DataMapExtensions.ToDTO <FlightRouteDTO>(List <BaseModel>)'需要类型为'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> ,但仅仅因为FlitghtRouteBaseModel继承而不使List<FlitghtRoute>继承自List<BaseModel> :它们是完全不同的类型。

相反,你可以做的是利用协方差 ,使用接口而不是具体类型。

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

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

这是因为IEnumerable<T>是一个具有协变类型参数的接口。 通过查看引用源 ,您将注意到此接口声明为out T作为泛型类型参数,这表示T是协变的,并且当我们使用IEnumerable<T>时可以用任何继承的类型替换。

您可以引入带约束的第二个类型参数:

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

解决这个问题的更好方法可能是更改签名,如下所示:

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

您实际上不需要接受List ,因为您没有使用值执行任何“特定于列表”的操作,并且AutoMapper会理解您传递给它的任何“集合”类型。 IEnumerable<T>就足够了,因为它与T ,它现在可以正常工作:

// works
List<FlightRouteDTO> bar = new List<FlightRoute>().ToDTO<FlightRouteDTO>();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM