Повреждает ли исключение в конце конструктора объект? - PullRequest
1 голос
/ 16 декабря 2011

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

    public Instrument(CalibrationData calibration)
    {
        _camera = new Camera();
        _driver = new Driver();

        if (_camera.GetUniqueId() != calibration.GetCameraUniqueId())
           throw new WrongCalibrationException("Calibration file was obtained on different equipment.");
         //Don't write anything here. Exception has to be the last code in the constructor.
    }

, а затем где-то еще

try
{
    instrument = new Instrument(calibration);
}
catch (WrongCalibrationException e)
{
    MessageBox.Show("You tried to load calibration obtained on different device.");
}

Я не могу проверить идентификатор перед подключением к устройству.

Этот вопросфактически состоит из двух.

  1. Правильно ли мое решение?Я хочу автоматически проверить правильность калибровки и не полагаться на то, что программист использует вызов моего кода для вызова другого метода (что-то вроде Instrument.AreYouProperlyCalibrated ())

  2. Правильно ли построен объект, когдаисключение выдается в конце конструктора?Я немного боюсь, что C # делает что-то вроде mumbo jumbo после завершения конструкции, и что это может отличаться в случае, если ctor выдает исключение.

Спасибо

Ответы [ 5 ]

3 голосов
/ 16 декабря 2011

Экземпляр уже полностью существует до начала конструктора (действительно, вы даже можете полностью обойти все конструкторы и все же получить действительный экземпляр) - это просто означает, что любой код инициализации, который не выполнялся, победил ' т выполнил.

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

_camera.HereIsMe(this);

или

SomeExternalObject.Track(this);

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

public static YourType Create(args) {
    // TODO: perform enough work to validate
    return new YourType(validated args);
}

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

2 голосов
/ 16 декабря 2011

Вы можете генерировать исключения из любого места в своем коде.

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

Так что я бы сказал, что ваш подход, учитывая только тот код, который вы разместили, в порядке. Очевидно, что могут быть другие проблемы, связанные с вещами, которые могут быть в конструкторах Camera и Driver (вещи не расположены и т. Д.), Но это другое дело.

2 голосов
/ 16 декабря 2011

Это вопрос предпочтений. Например, DateTime вызывает исключение в своем конструкторе . Если вы не хотите, вы можете использовать статический метод, такой как Build(Calibration calibration). Рекомендуется использовать XML-комментарии, чтобы пользователи вашего типа знали, что конструктор создает исключение в теге <exception>.

1 голос
/ 16 декабря 2011

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

Бросок ArgumentNullException в конструкторе?

http://bytes.com/topic/c-sharp/answers/518251-throwing-exception-constructor

http://blog.aggregatedintelligence.com/2009/04/can-constructors-throw-exceptions.html

0 голосов
/ 22 мая 2014

Я хотел бы добавить к ответу Марка, указав, что объекты Camera и Driver должны вводиться в класс. См. Эту (одну из многих) статей по реализации внедрения зависимостей в C #

Надеюсь, меня не застанут за это мнение. ;)

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