Подтвердить что ты не робот

Методы в конструкторах, плохо?

У меня есть форма окна, и у меня есть класс, который проверяет текстовый файл, чтобы убедиться, что он имеет определенный аспект. Теперь у меня есть методы в конструкторе, и это кажется немного странным. Должен ли я просто оставить конструктор пустым и реализовать метод типа start() и вызвать его? Пока что мой код выглядит как

public class Seating
{
    private int segments = 0;
    public Seating()
    {
        checkInvoice();
        getSegmentCount();          
    }
}
4b9b3361

Ответ 1

У меня есть методы в конструкторе, и кажется немного странным

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

В общем, это прекрасно, хотя.

Ответ 2

Нет ничего плохого в вызове не-виртуальных методов в конструкторе. Когда ваш конструктор срабатывает, ваш родительский объект полностью сконструирован. Однако вы не хотите вызывать какие-либо виртуальные методы, поскольку они могут быть переопределены подклассами, которые будут выполнять код внутри них, если они не будут полностью построены.

Ответ 3

Виртуальные вызовы метода в конструкторе no-go (с крошечным исключением закрытых классов, что делает метод не виртуальным).

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

Ответ 4

Вообще говоря, ваш конструктор должен только настраивать состояние объекта. Возможно, это может означать вызовы. Я бы сказал, что использование очень длинных методов - это не очень хорошая идея. Пользователь вашего класса не ожидал бы, что конструктор будет дорогостоящим методом.

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

Вот пример того, как он может быстро вернуться:

public class MyBase
{
        protected MyBase()
        {
                this.VirtualMethod();
        }

        protected virtual void VirtualMethod()
        {
                Console.WriteLine("VirtualMethod in MyBase");
        }
}

public class MyDerived : MyBase
{
        private readonly string message = "Set by initializer";

        public MyDerived(string message)
        {
                this.message = message;
        }

        protected override void VirtualMethod()
        {
                Console.WriteLine(this.message);
        }
}

Теперь, скажем, у вас есть этот код в другом месте:

MyDerived d = new MyDerived("Called from constructor");

Как вы думаете, что будет показано на консоли? Если вы сказали "Установить по инициализатору", значит, вы правы.

Вот почему:

  • Все инициализаторы полей выполняются перед кодом в конструктор.
  • Компилятор С# добавляет вызов базовому конструктору до все, что определено пользователем. В этом случае он вызывает запрос MyBase, который вызывает VirtualMethod(). Поскольку тип времени выполнения d MyDerived, переопределение VirtualMethod() в MyDerived - это казнены. И теперь, поскольку тело конструктора MyDerived не имеет Выполнено еще, this.message имеет значение, которое оно было дано в initalizer.
  • Теперь выполняется тело конструктора MyDerived.
  • Позднее вызовы VirtualMethod() в этом экземпляре теперь будут распечатываться "Вызывается из конструктора".

Ответ 5

В общем правиле есть методы, которые очень тривиальны и вряд ли порождают исключения в конструкторе. Если методы могут выйти из строя по какой-либо причине (доступ к файлам или отсутствует, проблема с БД, нулевая ссылка...), то это не должно быть в конструкторе, поскольку люди должны ожидать, что конструкторы не сбой (особенно беззазорные конструкторы, хотя общее руководство не указывается). Люди не должны ожидать, что var seating = new Seating(); станет источником ошибок.

Вы можете добавить методы Start()/Initialize() как методы экземпляра, как вы упомянули. Вы также можете добавить новый статический метод, который возвращает новый экземпляр класса после вызова двух методов, которые вам нужны, и сделать конструктор закрытым. Вы можете пойти дальше и использовать этот метод в новом классе Factory (делая внутренний конструктор). Вы можете придумать и другие способы сделать это.

Можно заметить, что любое значение, вычисленное или полученное в этих методах, является параметром конструктора (и не имеет конструктора без параметров), тогда конструктор будет присваивать эти параметры только соответствующим полям/свойствам. Метод или метод Factory в той же сборке или другой специализированной сборке "Услуги" могут отвечать за вызов методов, получение параметров, передачу их конструктору и возврат нового экземпляра класса. Это мой личный фаворит.

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

Обновление:

Вот рекомендации Microsoft для конструкторов:
Рекомендации по использованию конструктора

Цитата со страницы:

Минимизировать объем выполненной работы конструктор. Конструкторы должны не делать больше, чем захватывать параметр или параметры конструктора. Это задерживает стоимость выполнения дальнейшие операции до тех пор, пока пользователь не использует специфическая особенность экземпляра.

Ответ 6

Вот некоторые полезные рекомендации по дизайну для использования конструктора:

Конструктор Конструктор (MSDN)

Текст снят с:

Рекомендации по разработке рамок: соглашения, идиомы и шаблоны для многоразовых библиотек .NET

Это достойная покупка.

То, что я укусил много лет назад, было: "Не называть виртуальных членов на объекте внутри своих конструкторов".