派生自异常类是在C#中使对象"可抛出"的唯一方法吗?

use*_*298 4 .net exception-handling object

我可以解决一下如何使我的非异常对象变为'throwable',以便在try块中声明任何局部变量,就像obj在下面的try块中一样

try
{ 
   SomeObject obj = new SomeObject(); 
}catch {}
Run Code Online (Sandbox Code Playgroud)

可以跨越范围边界到catch {}子句?我想obj在catch {}子句中使用该实例,即使它的状态被破坏了.这有可能吗?

也许可能(?)因为C#编译器可能做的类似(对于优化我假设?)并允许catch子句接收任何System.Object但我不能在VS中使用它,对于这个方法:

public void Foo()
{

    try
    {
    }
    catch(Exception ex)
    {
    }

    try
    {
    }
    catch
    {
    }

}
Run Code Online (Sandbox Code Playgroud)

生成这个IL:

.method public hidebysig instance void  Foo() cil managed
{
  // Code size       22 (0x16)
  .maxstack  1
  .locals init ([0] class [mscorlib]System.Exception ex)
  IL_0000:  nop
  .try
  {
    IL_0001:  nop
    IL_0002:  nop
    IL_0003:  leave.s    IL_000a
  }  // end .try
  catch [mscorlib]System.Exception 
  {
    IL_0005:  stloc.0
    IL_0006:  nop
    IL_0007:  nop
    IL_0008:  leave.s    IL_000a
  }  // end handler
  IL_000a:  nop
  .try
  {
    IL_000b:  nop
    IL_000c:  nop
    IL_000d:  leave.s    IL_0014
  }  // end .try
  catch [mscorlib]System.Object     /* <-- I want to do like this*/
  {
    IL_000f:  pop
    IL_0010:  nop
    IL_0011:  nop
    IL_0012:  leave.s    IL_0014
  }  // end handler
  IL_0014:  nop
  IL_0015:  ret
} // end of method Class::Foo
Run Code Online (Sandbox Code Playgroud)

有没有一种方法(托管/未管理)像这样'作弊'并为该SomeObject类型定义'throwable'行为,以便我可以保留从有意义的类继承的权利,而不必从异常类继承只需创建一个对象'扔掉的?

如果我喜欢这个(我现在几乎都这样做)怎么样:

SomeObject obj = null; 
try
{ 
   obj = new SomeObject(); 
}catch {}
Run Code Online (Sandbox Code Playgroud)

如果在try子句内部或外部定义obj,性能会变慢,因为t看起来它们都在方法(而不是try scope)存储变量中生成相同的本地 - 你可以.locals init ([0] class ClassLibrary.Class obj在任何一种情况下进入IL,所以如果变量永远不会变慢刚开始?换句话说,如果我已经在方法代码中的任何地方SomeObject obj = null;定义但是我从不将它初始化为实际的实例,如果我的varuable定义在try/catch范围内或全局到整个函数范围,那么它是否重要(性能明智)在try/catch中?SomeObject

Jon*_*eet 5

(编辑:对不起,我刚刚看到你在帖子的最后建议这一点.基本上这是正确的做法!)

不,你不能抛出任何不是从Exception派生的东西.但是反正这样做是错误的 - 只需先声明变量:

SomeObject obj = null;
try
{ 
    obj = new SomeObject(); 
    // Other stuff
}
catch (IOException e) // Or whatever
{
    // Now you can refer to obj
}
Run Code Online (Sandbox Code Playgroud)

请注意obj,如果在为变量赋予其新值之前抛出异常(例如,如果SomeObject构造函数引发异常),则可能为null .

不,你不会受到由于这种任何性能问题-至少,如果有任何影响,他们将是微不足道的.代码可能最终实际执行额外的分配,但是相关的可能性实际上是不存在的.

  • @Danny:我完全不同意.构造函数在C#中抛出异常是完全合理的,许多标准库类都可以.你想要什么*`new List <int>( - 10)`做什么?如果一个构造函数抛出一个获取资源的异常,这是一件坏事,在这种情况下它应该适当地处理它......但这是一个特例. (5认同)
  • 构造函数永远不应该抛出异常,否则就会有邪恶的代码需要删除. (2认同)
  • @Danny Chen:无法构造所需对象的新实例的构造函数是一种特殊情况.你怎么建议发出失败的信号呢? (2认同)