Секреты LINQ. Автогенерируемые свойства. Инициализаторы объектов и коллекций, страница 3

Типы переменных s и a будут вычислены компилятором. В первом случае типом переменной будет string, во втором — int[]. Обратите внимание на конструкцию new[]. Здесь не указан тип новой памяти, запрашиваемой у системы (в области managed heap). Ранее (в C# 2.0) следовало писать: int[] a = new int[] { 1, 2, 3, 4 };.

Рассмотрим еще один пример использования var. Здесь типом переменной v будет CultureInfo.

CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);

foreach (var v in cultures)

Console.WriteLine("{0,52}  {1}", v.EnglishName, v.IetfLanguageTag);

В следующем примере тип переменной font будет вычислен, как FontFamily. Вычислить его самостоятельно не так просто. К сожалению, даже класс InstalledFontCollection не просто обнаружить в MSDN.

InstalledFontCollection collection = new InstalledFontCollection();

foreach (var font in collection.Families)

Console.WriteLine(font.Name);

Автогенерируемые свойства

Довольно часто приходится добавлять в классы открытые свойства, которые имеют традиционный вид:

public string Name

{

get { return name; }

set { name = value; }

}

Строго говоря, такие свойства не нужны (достаточно сделать открытой переменную name и не вводить свойство), но на практике вы встретите большое количество таких решений, так как они упрощают привязку к данным. Вы помните, что механизм DataBinding работает только при наличии открытых свойств.

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

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

class Stud

{

public string Name { get; set; }

public List<int> Marks { get; set; }

}

Раскрывать код аксессоров get и set теперь нет необходимости — это сделает компилятор. Примеры использования технологии LINQ, которые в изобилии вы найдете в MSDN, довольно часто пользуются таким приемом и вы должны о нем знать.

Возникает справедливый вопрос: "А как же в этом случае защитить данные от произвола пользователя?" Ответ: пользуйтесь традиционным способом объявления свойств или частично защищайте внутреннюю переменную с помощью конструкций вида Asymmetric Accessor Accessibility.

public string Name { get; private set; }

public string Name { get; internal set; }

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

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

Пример нового способа инициализации объекта с помощью default-конструктора был приведен ранее.

Person alex = new Person(){ Name = "Alex", Birth = new DateTime(1994, 2, 26), Salary = 10000m };

Рассмотрим, как выглядит новый инициализатор массива объектов того же типа:

var persons = new[]

{

new Person(){ Name = "Bale", Birth = new DateTime(1981, 3, 26), Salary = 10000m },

new Person(){ Name = "Dale", Birth = new DateTime(1974, 1, 11), Salary = 15000m },

new Person(){ Name = "Gail", Birth = new DateTime(1964, 6, 12), Salary = 20000m }

};

Заметьте, что нет необходимости указывать тип массива. Он вычисляется (infered) автоматически. Ранее мы поступали либо так:

Person[] persons =

{

new Person("Alex", new DateTime(1981, 3, 26), 10000m),

. . .

}

либо так:

Person persons;

persons = new Person[]

{

new Person("Alex", new DateTime(1981, 3, 26), 10000m),

. . .

}

При этом в классе Person необходимо было иметь конструктор с параметрами. Рассмотрим, как выглядит новый способ инициализации динамической коллекции объектов того же типа: