Ну, надеюсь, у тебя есть ответ. Если нет, вы можете попробовать посмотреть в режиме отладки. подкласс B имеет доступ как к intVal. Они не являются полиморфными, поэтому они не переоцениваются.
Если вы используете ссылку B, вы получите intVal B. Если вы используете ссылку A, вы получите intVal. Это так просто.
Оба.OfType< T> и.Cast< T> возвратит список T, но значение этих двух методов отличается.
список. Фильтры OfType исходный список и возвраты все объекты, которые имеют тип T и пропускают тех, которые не имеют того типа.
список. Бросок броски все объекты в исходном списке к типу T, и выдают исключение для объектов, которые не могут быть брошены к тому типу.
В Вашем случае оба дали бы тот же результат, но использующий.Cast передаст Ваше намерение намного более ясно, таким образом, я рекомендовал бы использовать это.
List<InputField> list = (from i .... select i).Cast<IDataField>.ToList();
List<InputField> raw = (from i .... select i).ToList();
List<IDataField> result = raw.OfType<IDataField>().ToList();
Вы могли также использовать Список. ConvertAll.
Документация: http://msdn.microsoft.com/en-us/library/73fe8cwf.aspx
Пример:
List<IDataField> newList = oldList.ConvertAll(i => i as IDataField);
Так как список появляется от
List<InputField> list = (from i .... select i).ToList();
, Вы не могли только зафиксировать "выбор i" частей, чтобы вместо этого возвратить IDataField вместо этого? Что-то вроде этого:
List<InputField> list = (from i .... select (IDataField)i).ToList();
, Если это не работает, возможно, расширение "Броска" IEnumerable будет работать:
List<DataField> list2 = list.Cast<IDataField>();
На всякий случай: у меня есть мало опыта C#, но если эта универсальная конструкция означает то же самое, это делает в Java, затем Вы должны создавать совершенно новый Список, параметризованный супертипом. Другими словами, если каждый экземпляр Bangle
является также экземпляром Akthud
, он делает не , следуют, это каждый List<Bangle>
также List<Akthud>
.
причина этого состоит в том, что у Вас может быть две ссылки на это List<Bangle>
. Если вторая ссылка бросает и затем называет его List<Akthud>
, то разрешено добавить Akthud
к нему - но теперь первая ссылка имеет List<Bangle>
, чьи участники не весь Bangle
с. Нарушение!
Однако ответ B David должен действительно сделать то, что Вы хотите, правильно, AFAICT. (Это похоже на операцию копии.)
[И если я неправильно понимаю семантику дженериков C#, я надеюсь, что кто-то исправляет меня в комментарии!]
ConvertAll походит на лучшее решение, так как он не зависит от библиотеки Linq и короче и более интуитивен.
, Но они оба - скорее обходные решения, чем решения. Они оба создают новый набор с теми же данными. Должна быть поддержка универсальной ковариантности в .NET, т.е. upcasting в универсальных наборах, которые позволили бы Вам делать это естественно. Например:
List<IDataField> ls = (List<IDataField>)List<InputField>
От моего поиска до сих пор, моего заключения, то, что .NET с 3,5 не поддерживает эту функцию. Следовательно мы должны закончить с обходными решениями.
Это обсуждения темы:
Я не знаю, что прямой бросок имел бы желаемый эффект. Редкие несколько раз я сделал это, это обычно - что-то как:
List<InputField> list = .....
List<IDataField> list2 = new (List<IDataField>((IDataField[])list.ToArray()));