I have a function which needs to go through a class’ types and identify a specific type. If I find that type, I want to cast it to the type that I know it is. But in the code below, the following case is failing:
BaseTableObjectList<BaseTableObject> obj = pi.GetValue(item, null) as BaseTableObjectList<BaseTableObject>;
Here is the code. Basically, I am making an iterator which returns certain properties. Why can’t I cast?
foreach (PropertyInfo pi in item.GetType().GetProperties())
{
if (pi.PropertyType.BaseType == null) continue; // skip interfaces
if (!pi.PropertyType.BaseType.IsGenericType) continue; // only interested in childlists
Type[] types = pi.PropertyType.BaseType.GetGenericArguments();
// is my generic argument derived from baseObject?
if (typeof(BaseTableObject).IsAssignableFrom(types[0]))
{
// this is a child we want
log.Info(types[0].Name);
BaseTableObjectList<BaseTableObject> obj = pi.GetValue(item, null) as BaseTableObjectList<BaseTableObject>;
yield return obj;
}
}
The problem you have I think is one of covariance, which only applies to interfaces. If you had a
IBaseTableObjectList<out T> where T : BaseTableObjectthe cast wouldn’t fail. Covariance for generics is only supported on delegates and interfaces not on base classes:http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx
This is essentially the same problem is assigning a
List<string>to anIEnumerable<object>which is one of the examples in the linked article.