В своей книге C # в глубине Джон Скит пытается ответить на следующий вопрос:
Почему я не могу преобразовать List<string>
в List<object>
?
Чтобы объяснить это, он начал с фрагмента кода, который включает в себя следующие две строки:
Animal[] animals = new Cat[5]; //Ok. Compiles fine!
List<Animal> animals = new List<Cat>(); //Compilation error!
По мере чтения комментариев первая прекрасно компилируется , но второй дает ошибка компиляции .Я не очень понял причину.Джон Скит объяснил это тем, что сказал, что первый компилируется, потому что в .NET массивы ковариантны, а второй не компилируется, потому что генерики не ковариантны (вместо этого они инвариантны).И, кроме того, массивы ковариантны в .NET, потому что массивы ковариантны в Java, а .NET делает его похожим на Java.
Я не полностью удовлетворен этим кратким ответом.Я хочу узнать это более подробно, с некоторым пониманием того, как компилятор обрабатывает разницу, и как он генерирует IL и все.
Кроме того, если я напишу (взято из самой книги):
Animal[] animals = new Cat[5]; //Ok. Compiles fine!
animals.Add(new Turtle()); //this too compiles fine!
Он хорошо компилируется, но не работает во время выполнения.Если он должен потерпеть неудачу во время выполнения (что означает, что то, что я пишу, не имеет смысла), то почему он компилируется в первую очередь?Могу ли я использовать экземпляр animals
в своем коде, который также работает без ошибок времени выполнения?