CLR:如果构造函数失败,它会抛出异常吗?

时间:2009-06-28 04:14:56

标签: .net clr defensive-programming

在Delphi中,如果在构造对象期间发生异常:将释放任何已分配的内存并抛出异常。例如,以下 保证 要么返回有效的 Camera 对象,要么抛出异常:

Camera c = new Camera();

从不必须检查结果变量是否为null:

Camera c = new Camera();
if (c == null)
   throw new Exception("Error constructing Camera") //waste of time

CLR中是否也是如此?

还有其他的语法结构,其中返回值保证有效,或抛出异常?

  • 创建结构(例如矩形)?
  • 获得枚举成员?
  • Object.ToString()?
  • 的结果
  • 数学运算?

在进行数学运算的情况下:

Int32 aspect = 1650.0 / 1080.0;
if (aspect == null) 
   throw new Exception("Division of two numbers returned null")

2 个答案:

答案 0 :(得分:3)

.Net中的构造函数保证返回该对象类型的非null实例。实例是否有效取决于该类型的各个语义。

构造函数中抛出的异常不会被CLR任意吞下(尽管用户代码可以吞下它们)。 CLR将传播异常,就像在任何其他方法中抛出的异常一样,对象最终将被正确地垃圾收集。

至于你提及的其他案例

  • 创建结构:按定义,结构不能为空。构造函数中抛出的异常将正常传播
  • 获取枚举的成员:枚举是引擎/值的类型,并且永远不会为null
  • Object.ToString()的结果:这可以(并且遗憾地)为null。 String是一种引用类型,从ToString覆盖中返回null是完全合法的(请不要)。
  • 数学运算:这在很大程度上取决于项目的溢出设置和使用的特定类型(积分与浮点)。

这个数学问题几乎值得回答。一方面,对原始类型的数学运算的结果将永远不为空。但它仍然无效。例如,以下代码不会抛出,但结果是否有效取决于您的具体情况

float f1 = 1.0;
float f2 = f1 / 0;

此时f2是一个非常具体的浮点值,不代表实数。有效吗?取决于您的用例。

答案 1 :(得分:1)

是。我想这样说(因为失败也可能意味着逻辑失败):如果构造函数没有抛出异常,则返回值保证为非 - null所以你永远不必进行这样的检查。

创建结构(例如矩形):struct根本不能nullNullable类型被视为完全不同的类型,即typeof(int?) != typeof(int))。调用结构的构造函数会因抛出异常或返回实例而失败。

获取枚举的成员:enum只是一组常量。没有什么比“在运行时获得成员”。它在编译时被替换。

Object.ToString()的结果:与任何方法一样,它可以返回包含string的{​​{1}}类型的任何有效值,并且还可以抛出异常(在这种情况下,它不会' t根本不返回任何值。

数学运算:所有表达式都将返回一个值或抛出异常。返回值可以是该类型的任何有效值(例如,null永远不能是Int32)。