views:

472

answers:

4

I have the following inheritance:

internal abstract class TeraRow{}

internal class xRow : TeraRow {} // xRow is a child of TeraRow

public IEnumerable<TeraRow> Compare(MappedTables which, DateTime selectionStart
  , DateTime selectionEnd, string pwd)
{
    IEnumerable<xRow> result=CompareX();
    return  (IEnumerable<TeraRow>)result; //Invalid Cast Exception? 

}

Unable to cast object of type 'System.Collections.Generic.List1[xRow]' to type 'System.Collections.Generic.IEnumerable1[TeraRow]

Also why do I need to cast it at all?

+6  A: 

You need to cast it because IEnumerable<T> is not covariant on T. You can do this:

return result.Cast<TeraRow>();
mquander
Downcasting generic-typed lists... One of the few places where generics fall apart without explicitly defining composite interfaces.
Brian Rudolph
+1  A: 

See this question: .NET Casting Generic List

David
+1  A: 

You're running afoul of contravariance. You'd need c# 4.0 for that to work. The type IEnumerable can't be exchanged for IEnumerable in 2.0 to 3.5. The msdn article on it is http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

gjutras
A: 

If you need the casted list to perform like the original reference (setting an item at an index also sets the item in the original collection, you can create a wrapper class that implements IList<T>. (Unless I'm missing something), for a general purpose solution you'll need two due to generic constraint limitations:

public class UpCastList<FromType, ToType> : IList<ToType>
    where FromType : ToType

public class DownCastList<FromType, ToType : IList<ToType>
    where ToType : FromType

The other possibility is delegating the conversion:

public class CastList<FromType, ToType> : IList<ToType>
{
    public CastList(IList<FromType> source, Func<FromType, ToType> converter) { ... }
}

Edit: if you only need an IEnumerable<T>, then you can use the Cast<T> extension method as mentioned earlier.

280Z28