Почему тип "базовый" объект мой конкретный тип?
Это кажется очень простым вопросом, но, очевидно, я что-то упускаю. Я сделал тест:
class A
{
public override int GetHashCode()
{
Console.WriteLine(base.GetType().Name);
return 0;
}
}
Я ожидал найти "объект", но я нахожу "А". Я полагался на это поведение, чтобы вызвать базу GetHashCode
это конкретные случаи с реализацией, вызывая base.GetHashCode()
и я ожидал object
реализация должна быть вызвана.
В чем дело?
4 ответа
base.
метод изменения обозначений, который вызывается для переопределения virtual
методы (как GetHashCode
в вашем образце - base.GetHashCode()
звонки object.GetHashCode
, this.GetHashCode()
звонки A.GetHashCode()
). base.
также может использоваться для метода скрытого базового класса, но это не так в данном примере.
поскольку GetType
не является виртуальным, и тогда нет вызова this.GetType()
а также base.GetType()
ведет себя идентично и вызывает object.GetType
который возвращает "Точный тип времени выполнения текущего экземпляра", как указано в документации
Вы путаете две совершенно разные вещи здесь. Один из них - это то, что называется реализацией метода, а другой - тип объекта во время выполнения.
object.GetType()
реализуется в object
и он всегда будет возвращать тип времени выполнения экземпляра, к которому он обращен.
Теперь, когда вы вызываете метод Foo
из любого данного класса, который не реализует Foo
а скорее наследует его от базового типа (ваш случай), base.Foo
или же Foo
по сути одно и то же, потому что единственный существующий Foo
является base.Foo
,
Однако, если класс реализует свой собственный Foo
поспорим, что он перекрывает виртуальный метод или скрывает не виртуальный метод, вызываемый метод будет другим. Не смущайтесь другими ответами, утверждающими, что поведение, которое вы видите, связано с GetType
не быть виртуальным, это не правда.
class A { int Foo() => 1;}
class B { }
class C { new int Foo() => 2; }
призвание Foo
или же base.Foo
изнутри B
то же самое, называя это изнутри C
не является; бывший вернется 2
последний 1
,
GetType()
всегда возвращает текущий тип, даже если вызван на base
, Чтобы получить базовый тип, вы можете сделать это:
class A
{
public override int GetHashCode()
{
Console.WriteLine(this.GetType().BaseType.Name);
return 0;
}
}
КСТАТИ base.GetHashCode()
работает как положено. Если вы позвоните в течение A
он выполнит object
реализация.
Коментарий Equalsk и его пост ( здесь для краткости) - это то, что вам нужно знать, но я сделаю дополнительный шаг и расскажу вам, почему вы так хотите.
Дано class A
наследуется только от System.Object
И учитывая class B
а также class C
подклассы class A
:
В классе B или C, base.GetType().Name
будет А. Вы ожидали этого, потому что это определено в подклассах, которые они наследуют от А.
В классе А вы все еще получаете А. Почему бы вам не захотеть object
?
Ответ прост. Скажем, я пишу такой метод:
public static void DoStuff(A input)
{
}
Я могу отправить DoStuff(input)
с input
классы А, В или С. Это потому, что их base
тип А. Это желательно. Мы не хотели бы неявно (и запутанно) исключать класс A из метода, который берет его производные; если бы мы это сделали, мы бы хотели, чтобы A был непостижимым интерфейсом.
Думать о System.Object
как предок. Если кто-то спрашивает вас, откуда вы, вы не отвечаете "Эволюция в Месопотамии", вы, как правило, просто обращаетесь к линии, имеющей отношение к вашему существованию. object
Класс по сути является первичным тиском, поэтому вы не будете ссылаться на него, если не попытаетесь что-то сказать, он должен принять все, что передано в качестве параметра, или не знаете, с каким типом объекта вы будете иметь дело.
Пример этого последнего случая:
public void DoStuffAgain(object x)
{
Messagebox.Show(x.GetType().Name);
}
В теории все, что происходит по трубе, будет object
, Вместо этого вы можете пройти этот класс "А" и захотите узнать "А", потому что это то, что вы прошли. Это верно, хотя х имеет тип object
,
BaseType
(свойство) вернет вашу базу для класса, как указано в других ответах. Это не приведет вас к object
Однако, если класс явно не наследует от чего-то другого.