Создание IList <T>для Item <U>? - PullRequest
2 голосов
/ 17 декабря 2009

Итак, у меня есть объект, скажем, Item<U>. Я хочу создать (n) (I)List<T>, содержащий коллекцию этих предметов. Проблема, с которой я сталкиваюсь, состоит в том, что в коллекции Item<U> может быть любое количество различных типов для U.

Я не могу понять, какую подпись использовать для IList. Я попробовал IList<Item<T>>, но, поскольку у меня нет (в классе, где должен использоваться IList) определение T (которое, как я уже сказал, в любом случае отличается), я не могу использовать эту подпись. Как лучше всего выполнить это требование?

Ответы [ 6 ]

5 голосов
/ 17 декабря 2009

Вам необходимо добавить не универсальный интерфейс к вашему Item<U> и сделать коллекцию из этих интерфейсов.

Невозможно создать коллекцию из IList<Item<T>>, где T - это некоторый базовый тип для множества различных типов объектов, которые вы хотите поместить в один и тот же список. Это со (ntra) -вариантность, которая специально запрещает это.

Так что вам нужно вместо этого добавить что-то общее, не общее, и составить список из этого. Например, вы можете заставить Item<T> реализовать IItem и вместо него создать IList<IItem>.

Это лучшее, что вы можете сделать.

2 голосов
/ 17 декабря 2009

IList предназначен для хранения одного типа. Чтобы решить, является ли что-то «единственным типом» или нет, вам нужно развернуть все параметры типа. Если взять ваш пример IList<Item<T>>, то T должен быть одним-единственным для конкретного экземпляра.

Например, вы можете выбрать Animal для T, а затем перейти к помещению Dog, Cat и Bear в IList. Но вы не можете поместить туда произвольные типы; они должны быть в состоянии быть преобразованы в тип, который вы указываете для T. И если ваши типы и не связаны таким образом, у вас нет другого выбора, кроме как иметь неуниверсальный интерфейс для вашего списка. Вы также можете рассмотреть возможность определения типа интерфейса для T, которому могут соответствовать все ваши соответствующие критериям элементы.

Как только вы определились, что будет T, вы можете сделать свой метод общим:

public void PrintItems<T>(IList<Item<T>> list)
{
  // ...
}
1 голос
/ 17 декабря 2009

Это немного неприятно в .Net 3, потому что все Item для разных U рассматриваются как независимые типы. Чтобы это работало, вы должны вручную ввести интерфейс для этого типа:

interface IItem{}

class Item<U>:IItem {...}

и теперь вы можете:

IList<IItem> list = new IList<IItem>();
list.Add(new Item<string>());
list.Add(new Item<int>());

В качестве альтернативы вы можете придерживаться неуниверсального списка.

1 голос
/ 17 декабря 2009

Вы можете сделать свой метод общим, как:

public void DoSomethingWithTheList<T>(IList<Item<T>> theList)
{
    //Do that something
}
0 голосов
/ 17 декабря 2009

Я думаю вы просто хотите IList<Item<U>>. Ключ в том, что T в имени универсального типа IList<T> является просто заполнителем - у него нет особого значения. Вам нужен список Item<U> с, поэтому просто создайте его.

Теперь, это, конечно, будет означать, что метод / класс, содержащий это IList, сам по себе будет общим в U, но, похоже, это продиктовано условиями вашего вопроса.

0 голосов
/ 17 декабря 2009

Вы можете попробовать это

class Item<U>
{
   ...
}


class Item : Item<object> {
   ...
}

....
IList<Item> itemList;
...