Вызов перегружаемого конструктора с помощью ключевого 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Вызов перегружаемого конструктора с помощью ключевого



Слова this

Когда приходится работать с перегружаемыми конструкторами, то иногда очень по­лезно предоставить возможность одному конструктору вызывать другой. В С# это дает­ся с помощью ключевого слова this. Ниже приведена общая форма такого вызова.

имя_конструктора (список_параметров1): this(список_параметров2)

{

//... Тело конструктора, которое может быть пустым.

}

В исходном конструкторе сначала выполняется перегружаемый конструктор, спи­сок параметров которого соответствует критерию список_параметров2, а затем все остальные операторы, если таковые имеются в исходном конструкторе. Ниже приве­ден соответствующий пример.

Листинг 8.22

// Продемонстрировать вызов конструктора с помощью this.

 

using System;

 

class XYCoord

{

public int x, y;

 

public XYCoord(): this(0, 0)

{

Console.WriteLine("В конструкторе XYCoord()");

}

 

public XYCoord(XYCoord obj): this(obj.x, obj.y)

{

Console.WriteLine("В конструкторе XYCoord(obj)");

}

 

public XYCoord(int i, int j) {

Console.WriteLine("В конструкторе XYCoord(int, int)");

x = i;

y = j;

}

}

 

class OverloadConsDemo

{

static void Main()

{

XYCoord t1 = new XYCoord();

XYCoord t2 = new XYCoord(8, 9);

XYCoord t3 = new XYCoord(t2);

 

Console.WriteLine("t1.x, t1.y: " + t1.x + ", " + t1.y);

Console.WriteLine("t2.x, t2.y: " + t2.x + ", " + t2.y);

Console.WriteLine("t3.x, t3.y: " + t3.x + ", " + t3.y);

}

}

Выполнение этого кода приводит к следующему результату.

В конструкторе XYCoord(int, int)

В конструкторе XYCoord()

В конструкторе XYCoord(int, int)

В конструкторе XYCoord(int, int)

В конструкторе XYCoord(obj)

tl.x, tl.y: 0, 0

t2.x, t2.y: 8, 9

t3.x, t3.y: 8, 9

Код в приведенном выше примере работает следующим образом. Единственным конструктором, фактически инициализирующим поля х и у в классе XYCoord, явля­ется конструктор XYCoord(int,int). А два других конструктора просто вызывают этот конструктор с помощью ключевого слова this. Например, когда создается объект t1, то вызывается его конструктор XYCoord(), что приводит к вызову this(0,0), который в данном случае преобразуется в вызов конструктора XYCoord(0,0). То же самое происходит и при создании объекта t2.

Вызывать перегружаемый конструктор с помощью ключевого слова this полез­но, в частности, потому, что он позволяет исключить ненужное дублирование кода. В приведенном выше примере нет никакой необходимости дублировать во всех трех конструкторах одну и ту же последовательность инициализации, и благодаря при­менению ключевого слова this такое дублирование исключается. Другое преимуще­ство организации подобного вызова перезагружаемого конструктора заключается в возможности создавать конструкторы с задаваемыми "по умолчанию" аргументами, когда эти аргументы не указаны явно. Ниже приведен пример создания еще одного конструктора XYCoord.

public XYCoord(int х): this(х, х) { }

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

Инициализаторы объектов

Инициализаторы объектов предоставляют еще один способ создания объекта и ини­циализации его полей и свойств. (Подробнее о свойствах речь пойдет позднее.) Если используются инициализаторы объектов, то вместо обычного вызова конструктора класса указываются имена полей или свойств, инициализируемых первоначально зада­ваемым значением. Следовательно, синтаксис инициализатора объекта предоставляет альтернативу явному вызову конструктора класса. Синтаксис инициализатора объекта используется главным образом при создании анонимных типов в LINQ-выражениях. (Подробнее об анонимных типах и LINQ-выражениях далее.) Но поскольку ини­циализаторы объектов можно, а иногда и должно использовать в именованном классе, то ниже представлены основные положения об инициализации объектов.

Обратимся сначала к простому примеру.

Листинг 8.23

// Пример, демонстрирующий применение инициализаторов объектов.

 

using System;

 

class MyClass

{

public int Count;

public string Str;

}

 

class ObjInitDemo

{

static void Main()

{

//Создать объект типа MyClass, используя инициализаторы объектов.

MyClass obj = new MyClass { Count = 100, Str = "Тестирование" };

 

Console.WriteLine(obj.Count + " " + obj.Str);

}

}

Выполнение этого кода дает следующий результат.

100 Тестирование

Как показывает результат выполнения приведенного выше кода, переменная экзем­пляра obj.Count инициализирована значением 100, а переменная экземпляра obj.Str - символьной строкой "Тестирование". Но обратите внимание на то, что в клас­се MyClass отсутствуют явно определяемые конструкторы и не используется обычный синтаксис конструкторов. Вместо этого объект obj класса MyClass создается с помо­щью следующей строки кода.

MyClass obj = new MyClass { Count = 100, Str = "Тестирование" };

В этой строке кода имена полей указываются явно вместе с их первоначальными значениями. Это приводит к тому, что сначала конструируется экземпляр объекта типа MyClass (с помощью неявно вызываемого по умолчанию конструктора), а затем задаются первоначальные значения переменных Count и Str данного экземпляра.

Следует особо подчеркнуть, что порядок указания инициализаторов особого зна­чения не имеет. Например, объект obj можно было бы инициализировать и так, как показано ниже.

MyClass obj = new MyClass { Str = "Тестирование", Count = 100 };

В этой строке кода инициализация переменной экземпляра Str предшествует инициализации переменной экземпляра Count, а в приведенном выше коде все про­исходило наоборот. Но в любом случае результат получается одинаковым.

Ниже приведена общая форма синтаксиса инициализации объектов:

new имя_класса [ имя = выражение, имя = выражение,... }

где имя обозначает имя поля или свойства, т.е. доступного члена класса, на который указывает имя_класса. А выражение обозначает инициализирующее выражение, тип которого, конечно, должен соответствовать типу поля или свойства.

Инициализаторы объектов обычно не используются в именованных классах, как, на­пример, в представленном выше классе MyClass, хотя это вполне допустимо. Вообще, при обращении с именованными классами используется синтаксис вызова обычного конструктора. И, как упоминалось выше, инициализаторы объектов применяются в основном в анонимных типах, формируемых в LINQ-выражениях.

Необязательные аргументы

В версии С# 4.0 внедрено новое средство, повышающее удобство указания аргу­ментов при вызове метода. Это средство называется необязательными аргументами и позволяет определить используемое по умолчанию значение для параметра метода. Данное значение будет использоваться по умолчанию в том случае, если для параме­тра не указан соответствующий аргумент при вызове метода. Следовательно, указывать аргумент для такого параметра не обязательно. Необязательные аргументы позволяют упростить вызов методов, где к некоторым параметрам применяются аргументы, вы­бираемые по умолчанию. Их можно также использовать в качестве "сокращенной" формы перегрузки методов.

Применение необязательного аргумента разрешается при создании необязательного параметра. Для этого достаточно указать используемое по умолчанию значение па­раметра с помощью синтаксиса, аналогичного инициализации переменной. Исполь­зуемое по умолчанию значение должно быть константным выражением. В качестве примера рассмотрим следующее определение метода.

static void OptArgMeth(int alpha, int beta=10, int gamma = 20) {

В этой строке кода объявляются два необязательных параметра: beta и gamma, при­чем параметру beta по умолчанию присваивается значение 10, а параметру gamma — значение 20. Эти значения используются по умолчанию, если для данных параметров не указываются аргументы при вызове метода. Следует также иметь в виду, что пара­метр alpha не является необязательным. Напротив, это обычный параметр, для кото­рого всегда нужно указывать аргумент.

Принимая во внимание приведенное выше объявление метода OptArgMeth (), последний можно вызвать следующими способами.

// Передать все аргументы явным образом.

OptArgMeth(1, 2, 3);

// Сделать аргумент gamma необязательным.

OptArgMeth(1, 2);

// Сделать оба аргумента beta и gamma необязательными.

OptArgMeth(1);

При первом вызове параметру alpha передается значение 1, параметру beta - значение 2, а параметру gamma - значение 3. Таким образом, все три аргумента за­даются явным образом, а значения, устанавливаемые по умолчанию, не используются. При втором вызове параметру alpha передается значение 1, а параметру beta - зна­чение 2, но параметру gamma присваивается устанавливаемое по умолчанию значение 20. И наконец, при третьем вызове упомянутого выше метода параметру alpha пере­дается значение 1, а параметрам beta и gamma присваиваются устанавливаемые по умолчанию значения. Следует, однако, иметь в виду, что параметр beta не получит устанавливаемое по умолчанию значение, если то же самое не произойдет с параме­тром gamma. Если первый аргумент устанавливается по умолчанию, то и все остальные аргументы должны быть установлены по умолчанию.

Весь описанный выше процесс демонстрируется в приведенном ниже примере программы.

Листинг 8.24

// Продемонстрировать необязательные аргументы.

 

using System;

 

class OptionArgDemo

{

static void OptArgMeth(int alpha, int beta=10, int gamma = 20)

{

Console.WriteLine("Here is alpha, beta, and gamma: " +

alpha + " " + beta + " " + gamma);

}

 

static void Main()

{

// Передать все аргументы явным образом.

OptArgMeth(1, 2, 3);

 

// Сделать аргумент gamma необязательным.

OptArgMeth(1, 2);

 

// Сделать оба аргумента beta и gamma необязательными.

OptArgMeth(1);

}

}

Результат выполнения данной программы лишь подтверждает применение ис­пользуемых по умолчанию аргументов.

Это аргументы alpha, beta и gamma: 12 3

Это аргументы alpha, beta и gamma: 1 2 20

Это аргументы alpha, beta и gamma: 1 10 20

Как следует из приведенного выше результата, если аргумент не указан, то используется его значение, устанавливаемое по умолчанию.

Следует иметь в виду, что все необязательные аргументы должны непременно ука­зываться справа от обязательных. Например, следующее объявление оказывается не­действительным.

int Sample(string name = "пользователь", int userId) { // Ошибка!

Для исправления ошибки в этом объявлении необходимо указать аргумент userId до аргумента паше. Раз уж вы начали объявлять необязательные аргументы, то ука­зывать после них обязательные аргументы нельзя. Например, следующее объявление также оказывается неверным.

int Sample(int accountld, string name = "пользователь", int userId)

{ //Ошибка!

Аргумент name объявляется как необязательный, и поэтому аргумент userId сле­дует указать до аргумента паше (или же сделать его также необязательным).

Помимо методов, необязательные аргументы можно применять в конструкторах, ин­дексаторах и делегатах. (Об индексаторах и делегатах речь пойдет далее.)

Преимущество необязательных аргументов заключается, в частности, в том, что они упрощают программирующему обращение со сложными вызовами методов и конструкторов. Ведь нередко в методе приходится задавать больше параметров, чем обычно требуется. И в подобных случаях некоторые из этих параметров могут быть сделаны необязательными благодаря аккуратному применению необязательных ар­гументов. Это означает, что передавать нужно лишь те аргументы, которые важны в данном конкретном случае, а не все аргументы, которые в противном случае должны быть обязательными. Такой подход позволяет рационализировать метод и упростить программирующему обращение с ним.



Поделиться:


Последнее изменение этой страницы: 2016-12-30; просмотров: 161; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.188.252.23 (0.024 с.)