У меня есть два IList<ICat>
, и я пытаюсь создать метод, который принимает IList<ICat>
и выполняет некоторую работу. У меня возникают проблемы с попыткой передать либо IList<PussyCat>
, либо IList<OtherCat>
, как PussyCat
, так и OtherCat
реализовать ICat
.
Я пробовал:
List<PussyCat> cats = ...
DoWork((IList<ICat>)cats);
и просто
DoWork(cats);
Но не скомпилируйте. Любые идеи?
Генерации С# являются инвариантными. Это означает, что List<string>
не является List<object>
.
С# 4.0 вводит безопасную ковариацию/контравариантность, но вы не сможете пройти List<string>
как List<object>
. Причина в том, что:
List<string> x = new List<string>();
List<object> o = x; // assume this statement is valid
o.Add(5); // Adding an integer to a list of strings. Unsafe. Will throw.
Массивы, с другой стороны, являются ковариантными. Вы можете передать string[]
методу, который ожидает object[]
.
DoWork
только foreach
ИНГ коллекции и ничего не меняется, вы можете объявить параметр как IEnumerable<ICat>
и вызовите его DoWork(cats.Cast<ICat>())
.
Существует две альтернативы:
Сделайте свой метод следующим:
public void DoWork< T > (IList< T > cats_) where T : ICat
{
//Do work;
}
Другая возможность - иметь такой метод, как
public void DoWork(IList< ICat > cats_)
{
//Do work;
}
и назовите его следующим образом:
{
//....Assuming: IList<PussyCat> iListOfPussyCats
List<PussyCat> pussyCats = new List<PussyCats>(iListOfPussyCats);
DoWork(pussyCats.ConvertAll<ICat>( c => c as ICat);
}
Если метод действительно не требует прямой индексации (IList<T>
) и не требует добавления/удаления элементов (ICollection<T>
), то передайте IEnumerable<T>
. Методы расширения Cast<T>()
позволяют передавать любые IList
из [insert ICat
-derived type] в качестве IEnumerable<ICat>
.
До появления С# 4.0, который поддерживает поддержку co и contra variance, вы можете уйти от чего-то вроде этого:
public void DoWork(IEnumerable<ICat> cats)
{
//do something
}
List<PussyCat> pussyCats = new List<PussyCat>;
List<OtherCat> otherCats = new List<OtherCat>;
DoWork(pussyCats.OfType<ICat>);
DoWork(otherCats.OfType<ICat>);
OfType
возвращает IEnumerable
не IList
.