Конструктор Инициализатор Оптимизация? - PullRequest
3 голосов
/ 19 февраля 2011

ПРИМЕЧАНИЕ: я работаю в .NET 3.5 здесь.

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

public Person(string name, int age, string job, bool isMale)
{  
    Name = name;
    Age = age;
    Job = job;
    IsMale = isMale;
}  

public CollegeStudent(string name) : this(name, 18) {}

public CollegeStudent(string name, int age) : this(name, age, "Student") {}

public CollegeStudent(string name, int age, string job) : this(name, age, job, true) {}

public CollegeStudent(string name, int age, string job, bool isMale) : base(name, age, job, isMale) {}

Достаточно ли умен компилятор, чтобывидите, что единственное, что делают дочерние конструкторы - это связывание друг с другом и, в конечном счете, просто вызов базового конструктора?Таким образом, он мог бы просто изменить инициализаторы этого конструктора так, чтобы он вызывал базовый конструктор непосредственно во время компиляции?

Таким образом, он по сути изменил бы все на это:

public CollegeStudent(string name) : base(name, 18, "Student", true) {}

public CollegeStudent(string name, int age) : base(name, age, "Student", true) {}

public CollegeStudent(string name, int age, string job) : base(name, age, job, true) {}

public CollegeStudent(string name, int age, string job, bool isMale) : base(name, age, job, isMale) {}

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

Ответы [ 5 ]

6 голосов
/ 19 февраля 2011

Компилятор C # будет идти назад вниз по цепочке конструкторов, пока не достигнет конструктора для Object. Я не думаю, что есть что оптимизировать, когда дело доходит до цепных конструкторов, так как вы их используете. Чтобы убедиться в этом, вы можете попробовать скомпилировать этот код и затем использовать Reflector , чтобы взглянуть на оптимизированный код.

А пока я жду Джона Скита.

Редактировать

Я только что скомпилировал этот простой код в класс (.Net 3.5):

namespace Person {
    public class Person {
        private String Name;
        private int Age;
        private String Job;
        private Boolean IsMale;

        public Person(string name, int age, string job, bool isMale) {
            Name = name;
            Age = age;
            Job = job;
            IsMale = isMale;
        }
    }

    public class CollegeStudent : Person {
        public CollegeStudent(string name) : this(name, 18) { }
        public CollegeStudent(string name, int age) : this(name, age, "Student") { }
        public CollegeStudent(string name, int age, string job) : this(name, age, job, true) { }
        public CollegeStudent(string name, int age, string job, bool isMale) : base(name, age, job, isMale) { }
    }
}

Используя Reflector, я обнаружил, что компилятор C # не оптимизировал ни один из конструкторов так, как вы предлагали.

5 голосов
/ 19 февраля 2011

Если что-то и будет оптимизировано, то это должен быть компилятор JIT, а не компилятор C #. В частности, если это вызывается из другой сборки, компилятор C # не может предположить, что код в CollegeStudent будет таким же во время выполнения, как и во время компиляции.

Как говорят SimpleCoder и Jim, вам не следует об этом беспокоиться. Вероятность того, что это будет значительная проблема производительности, крошечная.

Как говорит Махеш, в C # 4 вы можете использовать один конструктор с необязательными параметрами, но вы должны знать, что даже если вы ориентируетесь на .NET 2.0 или .NET 3.5, любой, кто компилирует против вашего кода с компилятор C # 2 или C # 3 не сможет использовать тот факт, что некоторые параметры являются необязательными, и будет вынужден указать все из них.

3 голосов
/ 19 февраля 2011

Если вы используете C # 4.0, используйте дополнительные параметры, которые более удобны, чем краткие.

public Person(string name, int age = 18, string job = "Student", bool isMale = true)
{  
    Name = name;
    Age = age;
    Job = job;
    IsMale = isMale;
}

Теперь вы можете использовать,

public CollegeStudent(string name) : base(name) {}

public CollegeStudent(string name, int age) : base(name, age) {}

public CollegeStudent(string name, int age, string job) : base(name, age, job) {}

public CollegeStudent(string name, int age, string job, bool isMale) 
                      : base(name, age, job, isMale) {}
2 голосов
/ 19 февраля 2011

Я не знаю, достаточно ли умен компилятор, чтобы устранить «бесполезные накладные расходы» конструкторов, соединяющихся друг с другом. Но действительно ли это имеет значение? Вопрос, который вы должны задать себе, заключается в том, действительно ли те несколько микросекунд, которые можно сэкономить, написав вторую версию, действительно стоят затрат на ремонтопригодность. Действительно ли вы будете выполнять столько вызовов конструктора, чтобы эти несколько микросекунд на вызов имели значение. На всех?

1 голос
/ 19 февраля 2011

Вам известен новый синтаксис:

CollegeStudent student = new CollegeStudent
{
  Name = "Bob",
  Age = 21,
  Job = "Spaceman",
  IsMale = true,
};

Подобные конструкторы в наши дни не нужны, если только вам не нужно компилировать их в более старой версии Visual Studio.

...