在构造函数的末尾抛出异常会损坏对象吗?

时间:2011-12-16 08:13:22

标签: c# exception constructor

我正在开发与外部设备通信的软件。该设备需要一组初始化值(calibrationData)。这些校准数据因设备而异。在第一版本中,校准数据可以由用户选择,因此用户可能意外地加载在不同件上获得的校准数据。该设备可以工作,但测量不正确。 我有

    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.");
}

在连接到设备之前,我无法检查ID。

这个问题实际上包含两个。

  1. 我的解决方案是否正确?我想自动测试正确校准的使用,而不是依赖程序员使用我的代码调用另一种方法(像Instrument.AreYouProperlyCalibrated())

  2. 在构造函数结束时抛出异常时,是否正确构造了对象?我有点害怕在构造完成后C#正在做一些mumbo jumbo,并且如果ctor抛出异常,这可能会有所不同。

  3. 由于

5 个答案:

答案 0 :(得分:3)

在构造函数开始之前,实例已经完全存在(实际上,你甚至可以完全绕过所有构造函数并仍然获得一个有效的实例) - 它只是意味着任何未执行的初始化代码都赢了没有执行。

例如,虽然不是一个好主意,但您可以在构造函数中传递该类型的对象实例 out ,即

_camera.HereIsMe(this);

SomeExternalObject.Track(this);

所以没有太多可怕的事情会发生,因为就运行时而言,这个对象就像普通一样存在,必须妥善处理。但是,在某些情况下使用工厂更清晰:

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

但重申一下;如果存在问题,那么从构造函数中抛出并不是意料之外的,并且没有害处。

答案 1 :(得分:2)

这是一个偏好问题。例如,DateTime在其constructor中引发异常。如果您不愿意,可以使用Build(Calibration calibration)之类的静态方法。一个好的做法是使用XML注释让您的类型的用户知道构造函数在<exception>标记中抛出异常。

答案 2 :(得分:2)

您可以在代码中的任何位置抛出异常。

如果你的构造函数在某处抛出,并且抛出该对象,则不会创建该对象,或者更正确的是,它将被创建,但是你的代码执行流程将遵循异常,所以你不会在创建对象的代码分支中,所以就像根本没有创建对象一样。

所以我说你的方法,只考虑你发布的代码,没问题。显然,可能存在与CameraDriver构造函数(未处理的东西等)相关的其他问题,但这是另一回事。

答案 3 :(得分:1)

这是一个有争议的主题,但在一天结束时,在构造函数中抛出异常是完全有效的。以下是一些讨论和验证实践的链接:

Throwing ArgumentNullException in constructor?

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

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

答案 4 :(得分:0)

我想通过指出相机和驱动程序对象应该被注入到课程中来添加Marc的答案。在implementing Dependency Injection in C#

上看到这个(许多之一)文章

希望我不会因为这个意见而受到鞭挞。 ;)