I have the following class hierarchy:
public abstract class BaseData
{
//some properties
}
public class CoData : BaseData
{
//some properties
}
I am working with a method that requires the return type to be List<BaseData>
. In the method, I have access to List<CoData>
public List<BaseData> Save()
{
List<CoData> listCoData = GetData();
return listCoData;
}
If I understand correctly, I can upcast from a CoData
to a BaseData
. But, when I have a list, it errors out even if I explicitly try to typecast.
Error:
Error 118 Cannot implicitly convert type 'System.Collections.Generic.List<CoData>' to System.Collections.Generic.List<BaseData>'
EDIT:
mquander's Conversion approach seems to work for me in 3.0
Is downcasting done the same way as well? from
ie., Can I do this - List<CoData> listCoData = listBaseData.Cast<BaseData>().ToList();
Yes; welcome to variance. Ultimately, it isn't a list of BaseData
- for example, if you had another subclass, a List<BaseData>
would (at compile time) let you .Add
it... but the runtime type wouldn't let you. The compiler is stopping you making a mistake.
In some scenarios, generics can help here... I discuss this at the end of this blog entry. Note that .NET 4.0 variance doesn't apply to lists.
This is called "covariance" with respect to the parameter of your collection, and C# doesn't support this kind of covariance right now. In C# 4.0, user-defined types and some built-in types like IEnumerable<T>
will support this.
In the meantime, you can work around it by creating a new enumeration with explicitly cast members (you might want to think about changing the return types of your stuff here to IEnumerable<T>
so you don't have to actually cook up new collections all the time:)
public List<BaseData> Save()
{
List<CoData> listCoData = GetData();
return listCoData.Cast<BaseData>().ToList();
}
Depending on how GetData works, you might also consider a structure like this:
public List<T> Save<T>() where T : BaseData
{
return listCoData = GetData<T>();
}
EDIT: Actually, as Marc and others undoubtedly will point out, List<T>
can't be covariant like this because you can add members in ways that would break type safety if it were. However, if you sent back IEnumerable<T>
s instead, you could use covariance here.
EDIT 2: In response to your additional question:
Can I do this?
List<CoData> listCoData = listBaseData.Cast<BaseData>().ToList();
No. listBaseData.Cast<BaseData>().ToList();
returns an object of type List<BaseData>
which can't be cast directly to a List<CoData>
. That's why we had to go to this effort in the first place.
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