2009-07-15 8 views
3

Я следующее наследование:Почему этот родовой бросок не работает?

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? 

} 

Невозможно привести объект типа «System.Collections.Generic.List 1[xRow]' to type 'System.Collections.Generic.IEnumerable 1 [TeraRow]

Кроме того, почему я должен бросить его на всех?

+0

Этот тип трансляции будет поддерживаться в C# 4.0, выпущенный позднее в этом году. Функция, которая решает эту проблему, называется ковариантными генерическими аргументами. –

ответ

16

Вы должны бросить его, потому что IEnumerable<T> не ковариантны на T. Вы можете сделать это:

return result.Cast<TeraRow>(); 
+0

Списки типизированного типа Downcasting ... Одно из немногих мест, где дженерики разваливаются без явного определения составных интерфейсов. –

0

Если вам нужно, чтобы литой список выполнялся как исходная ссылка (установка элемента в индексе также устанавливает элемент в исходной коллекции, вы можете создать класс-оболочку, который реализует IList <T>, не для решения общего назначения (если я что-то не хватает), вы будете нуждаться в двух из-за общих ограничений ограничений:.

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

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

другая возможность делегирования преобразования:

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

Редактировать: если вам нужен только IEnumerable <T>, вы можете использовать метод расширения Cast <T>, как упоминалось ранее.

Смежные вопросы