Будет ли моему атрибуту присвоено значение по умолчанию, если я использую список инициализатора? - PullRequest
0 голосов
/ 30 ноября 2010

У меня есть такой класс, как

public class Revex
{
    public IEnumerable<char> AllCharacters = Enumerable.Range(0, 256).Select(Convert.ToChar).Where(c => !char.IsControl(c)).ToArray();
    // ...

Если я инициализирую его с

var r = new Revex { AllCharacters = "abcd" };

Будет ли выполнена эта строка выше или нет (Enumerable.Range ...)?Если бы я хотел, чтобы не вызывали, когда я так конструирую свой класс, как бы я это сделал?

У меня есть около 10 необязательных классов символов, поэтому я неЯ не хочу писать конструктор для каждой возможной их комбинации.

Ответы [ 3 ]

2 голосов
/ 30 ноября 2010

Это

var r = new Revex { AllCharacters = "abcd" };

Является ли синтаксический сахар для

var r = new Revex();
r.AllCharacters = "abcd";

Должно быть очевидно, что поле AllCharacters будет инициализировано значением по умолчанию.

Если вы не хотите использовать значение по умолчанию, вы можете сделать это

public class Revex{

  public IEnumerable<char> AllCharacters;

  public Revex(){
     AllCharacters = Enumerable.Range(0, 256).Select(Convert.ToChar).Where(c => !char.IsControl(c)).ToArray()
  }

  public Revex(IEnumerable<char> allCharacters){
    AllCharacters = allCharacters;
  }

}

Есть еще одна опция:

public class Regex{

    private static IEnumerable<char> DefaultAllCharacters(){ return Enumerable.Range.. }

    private IEnumerable<char> allCharacters;

    public IEnumerable<char> AllCharacters{
        get { return allCharacters ?? (allCharacters = DefaultAllCharacters()); }
        set { allCharacters = value; }
    }

}

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

2 голосов
/ 30 ноября 2010

Инициализированные переменные-члены, подобные этой, всегда инициализируются до выполнения кода в вашем конструкторе.

В этой ситуации у вас есть следующая последовательность

  1. Инициализация AllCharactersпеременная-член
  2. Запустить конструктор Revex (который может быть предоставленным компилятором по умолчанию конструктором «ничего не делать»)
  3. Назначить новое значение для AllCharacters

Есливы хотите избежать этой последовательности, вам нужно переместить инициализацию AllCharacters в ваш конструктор.

Если вы также хотите разрешить возможное переопределение, вам может понадобиться что-то вроде этого:

public class Revex
{
    public IEnumerable<char> AllCharacters;

    public Revex()
        : this( Enumerable.Range(0, 256)
                .Select(Convert.ToChar)
                .Where(c => !char.IsControl(c))
    {
        // Nothing
    }

    public Revex(IEnumerable<char> allCharacters)
    {
        AllCharacters = allCharacters.ToArray();
    }
}

Обновление 3 декабря

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

public class Revex
{
    public IEnumerable<char> AllCharacters
    {
        get
        {
            if (mAllCharacters == null)
            {
                // Default initialization
                mAllCharacters 
                    = Enumerable.Range(0, 256)
                      .Select(Convert.ToChar)
                      .Where(c => !char.IsControl(c)
            }

            return mAllCharacters;
        }
    }

    public Revex()
    {
        // Nothing
    }

    private IEnumerable<char> mAllCharacters;
}
1 голос
/ 30 ноября 2010

Если вы инициализируете переменную класса с ее объявлением, инициализация произойдет. Таким образом, в этом случае ваше поле будет установлено дважды: один раз при создании класса, а затем снова при установке свойства.

Если вы хотите, чтобы инициализация была необязательной, вам нужно объявить ее как:

public IEnunerable<char> AllCharacters;

Затем вам нужно будет инициализировать его в конструкторе или, как вы сделали, установив свойство.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...