2009-02-11 1 views
5

У меня есть IList<DerivedClass>, который я хочу отличить до ICollection<BaseClass>, но когда я пытаюсь выполнить явное литье, я получаю null. Можно ли это сделать без создания и заполнения новой коллекции?Литье общей коллекции на базовый тип

Edit: Так как я только хочу прочитать из коллекции, я перешел на использование шаблонного метода:

public void PopulateList<BaseClass>(ICollection<T> collection) 

Тогда я могу передать ему IList<DerivedClass>. Есть ли хороший способ кэшировать этот список, чтобы я мог обновить его, когда мне нужно. Мой первый наклон заключается в использовании:

Object cachedCollection; 
Type cachedType; 
public void PopulateList<BaseClass>(ICollection<T> collection) { 
    cachedCollection = collection; 
    cachedType = T; 

    // other stuff... 
} 

private void Refresh() { 
    PopulateList<cachedType>(cachedCollection as ICollection<cachedType>); 
} 

У кого-нибудь есть лучший способ сделать это?

+0

Образец кода будет очень полезен. Без этого трудно дать вам что-нибудь вроде полезного ответа. –

ответ

8

Короткий ответ: «Нет». Вам нужно будет создать новую коллекцию с новым типом BaseClass и заполнить ее.

Если вы думаете об этом, это имеет смысл. Если бы вы могли просто «бросить» свою коллекцию в BaseClass, вы могли бы вставить в нее что-то типа «BaseClass», тем самым вынудив простой объект BaseClass в коллекцию DerivedClass. Это победит цель создания коллекции с типом безопасности.

В крайнем случае, если у вас было два производных класса, Foo и Bar, вы могли бы принудительно включить объекты Bar в коллекцию объектов Foo, переведя коллекцию обратно в коллекцию BaseClass.

+0

Это имеет смысл.Я читаю только из коллекции, поэтому я не думал о том, что я хотел сделать. – dmo

+0

var baseCollection = (ICollection) производныйList.CastToList (); –

3

Я не думаю, что это возможно, и на самом деле это не должно быть:

class BaseClass {} 
class DerivedClass : BaseClass {} 
class OtherClass : BaseClass {} 

void test() 
{ 
    List<DerivedClass> list = new List<DerivedClass>(); 
    slice(list); //you want to do this 
} 

void slice(IList<BaseClass> list) 
{ 
    //yikes! adding OtherClass to List<DerivedClass> 
    list.Add(new OtherClass()); 
} 
+1

В .NET 4.0 эта ситуация разрешается с помощью ключевых слов «in» и «out». –

2

Переключение между родовыми контейнерами производных классов и базовых классов не поддерживается. (Он работает с массивами). Можно написать преобразователь типа, чтобы разумно выполнить этот переключатель без ручного копирования элементов между списками.

Проверить эту ссылку для описания вопроса/ограничения и решения: http://www.25hoursaday.com/weblog/CommentView.aspx?guid=AF7AA888-A227-454C-8687-71FA77186064

на день хорошая общая с поддержкой версия.

+0

Yep, ConvertAll - ваш друг здесь :) –

6

Это называется со-дисперсией и в то время как в настоящее время не поддерживается дженериками в .net, оно будет добавлено в рамки 4.0 (вместе с противоположным, что противоречит дисперсии).

Это отличное видео с PDC 2008 является сессия по фьючерсам C# задается Хейлсберг:

http://channel9.msdn.com/pdc2008/TL16/

+0

Спасибо за информацию, Джим. Я посмотрю на это. – dmo

2

Если .NET 3.5 является вариант, вы можете использовать метод Cast<T> расширения в System.Core.dll, чтобы получить чтения -только IEnumerable<T> для коллекции:

using System.Linq; 
... 
private void Refresh() { 
    PopulateList(cachedCollection.Cast<cachedType>()); 
} 
0

Вы можете бросить каждый элемент в новый итератор:

var collectionOfBase = (collectionOfDerived as IEnumerable).Cast<BaseClass>(); 

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

  • Нет связанных вопросов^_^