Почему этот универсальный бросок терпит неудачу? - PullRequest
4 голосов
/ 15 июля 2009

У меня есть следующее наследство:

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]

И зачем мне вообще разыгрывать его?

Ответы [ 4 ]

17 голосов
/ 15 июля 2009

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

return result.Cast<TeraRow>();
2 голосов
/ 15 июля 2009

См. Этот вопрос: Общий список .NET Casting

1 голос
/ 15 июля 2009

Вы столкнулись с противоречивостью. Вам нужно c # 4.0, чтобы это работало. Тип IEnumerable нельзя заменить на IEnumerable в версии 2.0 до 3.5. Статья MSDN об этом http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

0 голосов
/ 15 июля 2009

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

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 , тогда вы можете использовать метод расширения Cast , как упоминалось ранее.

...