как указать, что MyMethod будет возвращать IList из T, где T может быть всем, что наследует от A или экземплярами самого A?
Вам не нужно
Вы можете просто объявить, что он возвращает IList<A>
.Зачем?Поскольку - учитывая, что B
наследуется от A
- каждый элемент B
может быть передан там, где запрашиваемый тип A
.
Назовите это полиморфизмом по наследованию, принципу подстановки Лискова или дисперсии методаимя не имеет значения.Важно то, что следующие работы (проверенные на LinqPad):
public class A {}
public class B: A {}
public IList<A> MyMethod()
{
var result = new List<A>();
//add some items to result
result.Add(new B());
return result;
}
Генетические альтернативы
Фактически, вы можете сказать, что вы собираетесь вернуть IList<TA>
изапросите несколько производных типов (TB
, TC
...), чтобы заполнить его.Правильно, следующий пример также работает (проверено на LinqPad):
void Main()
{
MyMethod<A, B, C>();
}
public class A {}
public class B: A {}
public class C: A {}
public IList<TA> MyMethod<TA, TB, TC>()
where TB : TA, new()
where TC : TA, new()
where TA : class
{
var result = new List<TA>();
//add some items to result
result.Add(new B() as TA);
result.Add(new C() as TA);
return result;
}
Или, если вы хотите сохранить определенный базовый тип (скажем, вы хотите вернуть IList<A>
, но он на самом деле содержит элементы классовчто происходит от A
, то вы можете сделать это:
void Main()
{
MyMethod<B, C>();
}
public class A {}
public class B: A {}
public class C: A {}
public IList<A> MyMethod<T1, T2>()
where T1 : A, new()
where T2 : A, new()
{
var result = new List<A>();
//add some items to result
result.Add(new T1() as A);
result.Add(new T2() as A);
return result;
}
Вам не нужно, но вы можете
ОК, если вы действительно хотите сказать этовозвращает IList<T>
where T : A
. Затем скажите, что!
void Main()
{
MyMethod<B>();
}
public class A {}
public class B: A {}
//public class C: A {} //Even if I don't add that class
public IList<T> MyMethod<T>()
where T : A, new()
{
var result = new List<T>();
//add some items to result
result.Add(new T());
return result;
}
Да, что нельзя возвращать смесь элементов типа T
и элементов типа A
, потому что он говорит, что возвращает IList<T>
и не каждый элемент типа A
также является элементом типа T
.
Что происходит с вашим кодом
Посмотрите на ваш код:
public IList<A> MyMethod(){
IList<B> result = new List<B>();
//add some items to result
return result;
}
Вы пытаетесь вернуть IList<B>
, когда говорите, что собираетесь вернуть IList<A>
. Предположим, что это работает ... тогда что будет с вызывающей стороной вашего метода? Давайте посмотрим:
public class A {}
public class B: A {}
public class C: A {}
void Main()
{
//Hmmm... I need a IList<T>, let's call MyMethod!
IList<A> list = MyMethod();
//Cool, I got an IList<A>, now let's add some items...
var item = new C();
//Well, item is of type C...
// and C inherits from A, so I must be able to add it...
list.Add(item); //BOOM!
//It was actually an IList<B>!
// and C doesn't dervive from B, so you can't add it.
}
DFTBA!