Ключевое слово base в C#

При наследовании класса в методе производного класса часто возникает необходимость вызова метода либо доступа к полю, свойству или индексатору базового класса. Для этой цели предусмотрено ключевое слово base.

Это ключевое слово можно применять подобно любой другой переменной экземпляра, но его можно использовать только внутри блока конструктора экземпляра, метода экземпляра или средства доступа к свойству.

Применение его в статических методах не допускается. Это совершенно оправдано, потому что base открывает доступ к реализациям экземпляра базового класса, подобно тому, как this разрешает доступ к экземпляру — владельцу текущего метода.

Рассмотрим следующий блок кода:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class А {
public А( int var ) {
this.x = var;
}
public virtual void DoSomething () {
System.Console.WriteLine ( "A.DoSomething" );
}
private int x;
}
public class В : A {
public В ()
: base( 123 )
{ }
public override void DoSomething()
{
System.Console.WriteLine ( "B.DoSomething" );
base.DoSomething();
}
public class EntryPoint
{
static void Main()
{
В b = new В () ;
b.DoSomething ();
}

В этом примере продемонстрированы два применения ключевого слова base, и одно из них — в конструкторе класса В. Напомним, что класс не наследует конструкторы экземпляра. Однако при инициализации объекта иногда требуется явно вызвать один из конструкторов базового класса во время инициализации производного класса.

Это объясняет нотацию, примененную в конструкто??е экземпляра класса В. Инициализация базового класса происходит после объявления списка параметров конструктора производного класса, но перед блоком кода конструктора производного класса.

Второе применение ключевого слова base содержится в реализации В. DoSomething. Было принято решение, что при реализации метода DoSomething в классе В необходимо позаимствовать реализацию DoSomething из класса А. Реализацию A.DoSomething можно вызвать непосредственно из реализации В. DoSomething, снабдив вызов префиксом — ключевым словом base.
Если вы знакомы с виртуальными методами, то здесь, возможно, недоуменно пожмете плечами.

Если метод DoSomething виртуальный, а ключевое слово base ведет себя как переменная экземпляра базового класса, не случится ли так, что base.DoSomething на самом деле превратится в вызов В. DoSomething? В конце концов, так работает полиморфизм, и base.DoSomething — эквивалент вызова ( (В) this).DoSomething, что является просто приведением ссылки this к ссылке на класс В, и потому получится вызов В. DoSomething, не правда ли? Да, если бы это было так, то код в В.

DoSomething стал бы причиной бесконечного цикла. На самом деле никакого бесконечного цикла не будет. Когда ключевое слово base встречается внутри члена экземпляра при вызове виртуального метода, оно трактуется специальным образом. Обычно вызов виртуального метода на экземпляре означает вызов его наиболее “унаследованной” версии — в данном случае В. SomeThing.

Однако когда он вызывается через ключевое слово base, то вызывается наиболее “унаследованная” реализация метода базового класса. Поскольку А — базовый класс, a A.DoSomething — наиболее унаследованная версия метода DoSomething класса А, значит, base. DoSomething вызывает A.DoSomething.

Подобным образом можно реализовать переопределенный метод, заимствуя реализацию базового класса. Если вас интересуют подробности, то знайте, что в сгенерированном коде IL вызов через ссылку base происходит с использованием инструкции call, а не callvirt.

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100