The_Unknown_Member Ответов: 3

[C#] переменная времени выполнения и времени компиляции ?


namespace CSharp_Practicing
{

    class Program
    {

        static void Main(string[] args)
        {
            Animal a = new Dog(); // THE QUESTION IS ABOUT THIS VARIABLE !!!
        }
    }

    class Animal { }
    class Dog : Animal
    {
        public void SayBau()
        {
            Console.WriteLine("Baaaaaau");
        }
    }
    class Cat : Animal
    {
        public void SayMaw()
        {
            Console.WriteLine("Mawwwwwwwwwwwww");
        }
    }
}


Переменная a во время компиляции имеет тип Animal, а во время выполнения - тип Dog ? Прав ли я или понимаю это неправильно ?

Что я уже пробовал:

Задавая вопрос здесь в CodeProject.com

3 Ответов

Рейтинг:
2

CPallini

Грубо говоря, да.
Вы можете использовать его в любом контексте. Animal разрешен (следовательно, его тип "время компиляции"), однако его фактический тип во время выполнения является полиморфным, Dog.

Обратите внимание, что ваша иерархия классов не использует преимущества полиморфизма.


The_Unknown_Member

Хорошо не могли бы вы объяснить мне это пожалуйста:
объект o = 5;
объект y = 6;
объектом ой = о + г;
Приставка.WriteLine(oy.метод GetType());

Это все еще полиморфизм. Потому что каждый класс в .NET наследуется от системы.Объект, чтобы я мог назначить переменной типа System.Объект целочисленное значение и тип этой переменной во время выполнения будет целочисленным, а во время компиляции-системным.Объект. Я знаю, что это система.Объект не имеет перегрузки оператора " + " для целых чисел, но разве он не должен выполнять o + y во время выполнения и присваивать его обратно переменной oy ?

Edit: я думаю, что понял это. Это происходит потому, что после оператора присваивания oy я добавляю две переменные типа System.Объект (который содержит целые числа, но во время компиляции они все еще являются системой.Объект) и начиная с Системы.Объект не поддерживает арифметические операции для целых чисел, он не может выполнить задачу во время выполнения, но если я сделаю его объектом oy = 5 + 6; то он сможет, потому что 5 и 6 являются целочисленными литералами и не удерживаются системой.Объектная переменная. Правильно ли я все понял ?

Рейтинг:
2

Richard MacCutchan

Это всегда собака, так как вы создали ее таким образом в своей жизни. new заявление. На самом деле переменная не является чем-то во время компиляции, так как она не существует до тех пор, пока программа не будет запущена.


Ralf Meier

Я с тобой не согласен ...
Животное-это базовый тип. Если вы примерите а как животное с собакой, вы можете сделать это (потому что собака происходит от животного), но то, что вы получаете, - это только то, что является общим-это означает, что у вас нет метода Сайбау ...

Richard MacCutchan

Вы правы (вроде как). Хотя a объявляется как Animal тип, он все еще относится к Dog, от new заявление. Таким образом, вы можете бросить его до Dog и получить SayBau метод. Если бы он был создан как new Animal вы не сможете этого сделать.

Ralf Meier

Вот что я имел в виду ... ;)

Richard MacCutchan

Итак, теперь вы согласны с моими первоначальными комментариями?

Ralf Meier

И да, и нет ... но с вашими дополнительными комментариями ... потому что (для меня) исследователь не был уверен в том, что происходит с/когда выводится из чего-то ...

Richard MacCutchan

Я согласен. К счастью, F-ES Sitecore теперь все прояснила.

Ralf Meier

чтобы прояснить это :
Я очень ценю все ваши комментарии и ответы - это не голосование !!!

Richard MacCutchan

Я так не думал. И я также ценю комментарии и исправления от вас (и других, кто знает, о чем они говорят).

F-ES Sitecore

Метод SayBau *есть* на объекте, вы просто не можете получить к нему доступ с помощью "a", так как "a" указывает на подкласс. Если вы бросите" а " собаке, она станет доступной.

Ralf Meier

Вот что я имел в виду ... ;)

Рейтинг:
1

F-ES Sitecore

Animal a = new Dog(); 


Вы создаете две вещи, вы создаете объект (Dog) и ссылочную переменную (a). Объект-собака, он всегда будет собакой,и быть собакой-значит быть животным. Переменная, которую вы создаете, имеет тип Animal и указывает на животную часть объекта Dog. Поскольку объект "а" указывает на собаку, вы можете сделать это

Dog d = (Dog)a;


У вас по-прежнему есть только один объект (Dog), однако вы создали еще одну ссылочную переменную (d), которая указывает на собачью часть объекта. Итак, теперь у вас есть один объект (собака) и две опорные переменные, которые указывают на этот объект; "А", который смотрит на часть животного и может получить доступ только к свойствам и методам животного, и "d", который смотрит на часть собаки и может получить доступ к любому свойству или методу на части собаки или части животного (поскольку Собака наследует животное, Собака тоже считается животным).

А теперь подумайте вот о чем

Cat c = (Cat)a;


Будет ли это компилироваться? Да. Компилятор знает только, что "а" должно быть животным, поэтому вполне возможно, что это может быть кошка, но он не знает этого во время компиляции, поэтому дает вам преимущество сомнения. Однако во время выполнения он выдаст ошибку, так как нет" кошачьей "части объекта, на которую указывает" а", как" А " указывает на собаку.


Ralf Meier

Хорошо объяснил ... +5