вторник, 23 сентября 2008 г.

Readonly Auto-Implemented Properties

Вчера расстроился по поводу реализации auto-implemented properties в C# 3.0. Началось все с того, что прочитав документацию по этому вопросу довольно продолжительное время назад, и встретив там цитату
To create a readonly auto-implemented property, give it a private set accessor.
считал, что auto-implemented readonly свойства имеют отношение к ключевому слову readonly. Вот цитата из описания этого ключевого слова:
The readonly keyword is a modifier that you can use on fields. When a field declaration includes a readonly modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.
Именно на эту статью в документации ведет гиперссылка из статьи про auto-implemented свойства. Воображение рисовало такую реализацию этого нововведения компилятором, где бы код
class Foo
{
  public int MyProperty { get; private set; }

  public Foo(int p)
  {
      MyProperty = p;
  }
}
соответствовал бы следующей реализации:
class Foo
{
  private readonly int _autoGeneratedReadonlyField;

  public Foo(int p)
  {
      autoGeneratedReadonlyField = p;
  }

  public int MyProperty
  {
      get { return _autoGeneratedReadonlyField; }
  }
}
Таким образом, такая реализация auto-implemented свойства с private set аксессором, максимально соответствовала бы документации. Так получилось, что довольно долго я считал, что readonly auto-implemented свойства нельзя модифицировать нигде, кроме конструктора класса (либо статического конструктора, если свойство статическое). Оказалось, что private set не генерит ничего кроме private аксессора к свойству, обращение к которому разрешено из кода любого метода или свойства класса, либо вложенных классов.

Итого, использование readonly auto-implemented свойств не имеет никакого отношения к readonly полям класса. Зачем же тогда в документации стоит эта ссылка на описание ключевого слова readonly? Думаю, что кроме меня есть еще жертвы дезинформации.

Вообще говоря, поведение private set модификатора auto-implemented свойства выбрано правильно. И такое поведение нужно, но кроме этого нужна адекватная документация. Все же, эмуляция readonly полей нужна. И на форуме в RSDN было предложено несколько вариантов синтаксиса, которые могли бы быть реализованы. Например,
public readonly string MyString { get; }

public int Property { get; readonly set; }

public int Property { readonly; }
Удобен был бы способ инициализации таких свойств при объявлении (по аналогии с полями).

2 комментария:

  1. Реализую свойства вручную, не использую автосвойста, только для того чтобы везде вписать readonly. И мне себя не жалко, семантика дороже :-)

    ОтветитьУдалить
  2. В продакшн коде тоже делаю именно так. А в прототипе могу и полениться.

    ОтветитьУдалить