I have the following 2 extension methods
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);
}
}
}
The first method works perfectly fine.
//Note: FlightRoute inherits BaseModel
FlightRouteDTO foo = new FlightRoute().ToDTO<FlightRouteDTO>(); //This works!
However, the second method does not seem to work.
List<FlightRouteDTO> bar = new List<FlightRoute>().ToDTO<FlightRouteDTO>(); //This doesn't work!
The compiler is saying
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>'
But FlightRoute
is of type BaseModel
. If I change the type of bar
to explicitly be List<BaseModel> ...
then the problem goes away.
List<FlightRouteDTO> bar = new List<BaseModel>().ToDTO<FlightRouteDTO>(); //Why does it only work this way?
Am I missing something obvious?
That's just the expected behavior: you are trying to use a List<FlightRoute>
as a List<BaseModel>
, but just because FlitghtRoute
inherits from BaseModel
doesn't make List<FlitghtRoute>
inherit from List<BaseModel>
: they are completely different types.
What you could do, instead, is to leverage the use of Covariance, using interfaces instead of concrete types.
By changing your method signature to the following, you will notice that no compiler error will be generated:
public static List<T> ToDTO<T>(this IEnumerable<BaseModel> models)
{
return Mapper.Map<List<T>>(models);
}
That's because IEnumerable<T>
is an interface with a covariant type parameter. By looking at the reference source, you will notice that this interface is declared with out T
as generic type parameter, which indicates that T
is covariant, and may be replaced by any inherited type when we use IEnumerable<T>
.
You could introduce a second type parameter with a constraint:
public static List<T> ToDTO<T, K>(this List<K> models) where K : BaseModel
{
return Mapper.Map<List<T>>(models);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With