I'm trying to make a generic type for retrieving data from API, however I can't cast explicit type to T in Get method:
Classes are arranged as follows: PClass, MClass and SClass doesn't inherit over common parent (in fact they are just data model classes)
VMClass <- PagedResponse<T>, where T can be P-, M- or SClass
API sends very similar responses for all 3 Gets:
common string name
, etc, and P-, M- or SClass result[]
I have few extension methods for casting explicit types:
internal static List<VMClass> ToVMElement(this List<MClass> ms) { ... }
internal static List<VMClass> ToVMElement(this List<pClass> ps) { ... }
internal static List<VMClass> ToVMElement(this List<sClass> ss) { ... }
When I'm trying to use switch-case for deciding which operation I want to perform, I'm returning explicit type of PagedResponse<SClass>
(or P-
M-
) – experiencing CS0029 – Cannot implicitly convert classes
public static async Task<PagedResponse<T>> RetrieveApiData<T>(...)
{
switch (typeof(T))
{
case Type m when m == typeof(MClass):
PagedResponse<T> r = await GetMClasses(...); // await returns PagedResponse<MClass>
return r;
case Type S when s == typeof(SClass):
//...
}
//...
}
I understand that generic types are resolved at compilation, but I don't know how to accomplish that casting.
If you only have a small set of known classes, then generics is most likely the wrong solution. You would most likely be better of just specifying the type in the method name
Task<PagedResponse<MClass>> RetrieveApiMClas(...)
Task<PagedResponse<pClass>> RetrieveApipClass(...)
Task<PagedResponse<sClass>> RetrieveApisClass(...)
This should not be more code than using generics with a switch, and it removes the possibility of runtime errors.
If you do not know what type an API call will return you might be able to use a discriminated union. Something like a OneOf<MClass, pClass, sClass>
. That way the caller can handle each type in different ways. There is apparently a proposal open to include this in the language, but it was not included in c# 11.