簡體   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