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

В С# предусмотрено сокращение, которое можно использовать при инициализации новых экземпляров объектов. Наверняка вам часто приходилось писать код, подобный приведенному ниже:

1
2
3
Employee developer = new Employee();
developer.Name = "Fred Blaze";
developer.OfficeLocation = "Bl";

Сразу после создания экземпляра Employee немедленно выполняется инициализация доступных свойств экземпляра. Не правда ли, было бы здорово, если бы можно было делать все это в одном операторе? Разумеется, всегда можно создать специализированную перегрузку конструктора, принимающего параметры для инициализации нового экземпляра. Однако бывают случаи, когда удобнее этого не делать.

Новый синтаксис инициализатора объекта показан ниже:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System;
public class Employee
{
public string Name {
get;
set;
}
public string OfficeLocation {
get;
set;
}
public class InitExample {
static void Main()  {
Employee developer = new Employee {
Name = "Fred Blaze", OfficeLocation "Bl"
}

Обратите внимание на то, как инициализируется экземпляр developer в методе Main. “За кулисами” компилятор генерирует тот же код, какой получился бы в случае, если бы свойства инициализировались вручную после создания экземпляра Employee.

Поэтому такая техника работает только в случае доступности свойств — в данном случае Name и Off iceLocation — в точке инициализации.

Инициализаторы объектов можно даже вкладывать друг в друга, как показано в следующем примере:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System;
public class Employee
{
public string Name { get; set; }
public string OfficeLocation { get; set; }
}
public class FeatureDevPair {
public Employee Developer { get; set; }
public Employee QaEngineer { get; set; }
}
public class InitExample {
static void Main()  {
FeatureDevPair spellCheckerTeam = new FeatureDevPair {
Developer = new Employee {
Name = "Fred Blaze", OfficeLocation = "Bl"
QaEngineer = new Employee {
Name = "Marisa Bozza", OfficeLocation = "L42"
}

Обратите внимание, что два свойства spellCheckerTeam инициализируются с использованием нового синтаксиса. Каждый экземпляр Employee, присваиваемый свойствам, сам инициализируется посредством объектного инициализатора. И, наконец, посмотрите, как выглядит еще более краткий способ инициализации объектов, позволяющий сократить объем клавишного ввода за счет скрытого усложнения:

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
26
using System;
public class Employee
{
public string Name { get; set; }
public string OfficeLocation { get; set; }
}
public class FeatureDevPair {
private Employee developer = new Employee () ;
private Employee qaEngineer = new Employee () ;
public Employee Developer {
get {
return developer; }
set {
developer = value; }
}
public Employee QaEngineer {
get { return qaEngineer; }
set { qaEngineer = value; }
}
public class InitExample {
static void Main()  {
FeatureDevPair spellCheckerTeam = new FeatureDevPair {
Developer = {
Name = "Fred Blaze", OfficeLocation = "Bl", QaEngineer = {
Name = "Marisa Bozza", OfficeLocation = "L42"
}

Как видите, здесь появилась возможность опустить выражения new при инициализации свойств Developer и QaEngineer объекта spellCheckerTeam. Однако такой сокращенный синтаксис требует, чтобы поля spellCheckerTeam уже существовали перед установкой свойств, т.е. данные поля не должны быть null. В связи с этим пришлось изменить определение FeatureDevPair, чтобы создать содержащиеся экземпляры Employee в точке инициализации.

Если вы не инициализируете поля, раскрываемые свойствами, во время инициализации объекта, а затем позже напишете код, инициализирующий экземпляры этих объектов с использованием показанного выше сокращенного синтаксиса, то во время выполнения столкнетесь с неприятным сюрпризом. Ожидается, что в таких случаях код должен сгенерировать исключение NullReferenceException (нулевая ссылка).

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

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

Вы можете следить за любыми ответами на эту запись через 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