2015-02-24 3 views
0

В приведенном ниже примере я могу добавить List типа Animal. С Dog и Cat происходят от животных, List может содержать каждый. Однако, если у меня есть метод, который принимает List<Animal>, вы не можете передать ссылку List<Dog>. Если Dog происходит от животного, почему это недействительно? Однако, если у меня есть метод, который исключает параметр типа Object, и все объекты производятся от Object, он работает.Метод, который исключает объекты производного класса

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Animal> animals = new List<Animal>(); 
     animals.Add(new Dog() { Color = "Black" }); // allowed since Dog derives from Animal 

     List<Dog> dogs = new List<Dog>(); 
     dogs.Add(new Dog() { Color = "White" }); 

     Test(animals); 
     Test(dogs); // not allowed - does not compile 
     Test2(dogs); // valid as all objects derive from object 
    } 

    static void Test(List<Animal> animals) { 
     // do something 
    } 

    static void Test2(object obj) { 

    } 
} 

public class Animal { 

    public String Color { get; set; } 

} 

public class Dog : Animal { } 
public class Cat : Animal { } 
+1

Попробуйте 'статической силы Test (IEnumerable животных)' –

+2

поиска для 'ковариации и контрвариации в C#' –

+0

Как следует Selman22, посмотрите [здесь] (https://msdn.microsoft.com/it-it/ библиотека/dd799517 (v = vs.110) .aspx) –

ответ

2

Представьте себе, что Test(dogs) скомпилировать. Затем представьте, что Test() реализуется как следующим образом:

static void Test(List<Animal> animals) 
{ 
    animals.Add(new Cat()); // Where Cat is derived from Animal 
} 

Вы только что добавили кошку в список собак ... Очевидно, что не может быть разрешено. И вот почему это не так.

Однако, если вы только доступ к элементам списка, а не добавление в список, вы можете объявить Test() так:

static void Test(IEnumerable<Animal> animals) 
{ 
    foreach (var animal in animals) 
    { 
     // Do something with animal. 
    } 
} 

Затем вы можете передать любой тип коллекции, которая реализует IEnumerable<T>, такие как List<T> и простые массивы.

+0

Это имеет смысл теперь. – PhillyNJ

+0

Ну, добавление кошки к собакам обычно весело, поэтому я бы это разрешил ...;) – Gerino

+0

Собаки и кошки ... в том же 'List ' ... [Массовая истерия !!!] (https: //www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=0CCUQtwIwAQ&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D9S4cldkdCjE&ei=vZfsVI6mL- bHsQSBuYDgCw & usg = AFQjCNGzPe3S7AsY6QTfnKAu-096C6WMcQ & sig2 = 9ik5utUb2D5HjVV7AOZ8jw & bvm = bv.86475890, d.cGU) –

2

Звонок Test(dogs.Cast<Animal>().ToList()). Измените тип параметра на IEnumerable, чтобы пропустить ToList(), который создает копию.

int является object. List<Animal> - object, равно как и List<Dog>. Но List<Dog> НЕ List<Animal>.

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