【问题标题】:Need to explicitly throw an exception in C#?需要在 C# 中显式抛出异常?
【发布时间】:2019-07-03 22:18:25
【问题描述】:

是否需要在 try 块中显式抛出异常?如果我不在 try 块中抛出异常会怎样?

try
{
    // code that throws an exception
    throw new IndexOutofRangeException;
}
catch (IndexOutOfRangeException ex)    
{
   Console.WriteLine(ex.Message);
}

编辑:具体来说,假设 try 块中有代码生成异常但try没有throw 声明。会发生什么?

【问题讨论】:

  • 如果try块中的代码产生IndexOutofRange异常但我没有写“throw new IndexOutOfrangeException”,会发生什么?
  • 你问1)如果我在try-catch() 之外抛出异常会发生什么 2) 如果我的try 块是(没有显式/直接的throw 语句或可能间接引发异常的代码)会发生什么?
  • try 块中有代码会产生异常,但是 try 块没有 throw 语句。会发生什么?

标签: c# exception try-catch


【解决方案1】:

如果我不在 try 块中抛出异常会发生什么?

如果你不抛出异常,并且没有引发其他异常,catch 块将不会运行。代码将跳过 catch 块并继续执行之后的任何内容(包括 finally 块,如果有的话)。

想象一下,try 块中有代码生成异常但 try 块没有 throw 语句的情况。

catch 块仍将运行...当且仅当异常的 typecatch 块声明的类型匹配时。让我们看几个例子。首先是这个示例:

try
{
   double x = 1 / 0.0;
}
catch (DivideByZeroException ex)
{
    Console.WriteLine(ex.Message);
} 

在这种情况下,我们有导致DivideByZeroException 异常的代码。由于这与 catch 块中使用的类型匹配,因此异常处理程序将运行。

接下来:

try
{
   double x = 1 / 0.0;
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
} 

我们仍然有一个DivideByZeroException 异常...但是由于DivideByZeroException 继承自基本Exception 类型,因此仍然兼容并且catch 块将运行。

另一个:

try
{
   double x = 1 / 0.0;
}
catch (InvalidOperationException ex)
{
    Console.WriteLine(ex.Message);
} 

我们仍然有一个DivideByZeroException 异常,但这次catch兼容。在这种情况下,程序将因未处理的异常而崩溃(除非此异常在程序堆栈中的其他位置处理)。

还有一个:

try
{
   double x = 1 / 0.0;
}
catch (InvalidOperationException ex)
{
    Console.WriteLine(ex.Message);
} 
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

两个catch 块!第一个块不会运行,因为它与DivideByZeroException 类型不兼容。但是,第二个catch 块将运行,因为它是兼容的。异常处理完毕,程序可以继续运行。

最后:

double DbyZ(double numerator)
{
    try 
    {
        return numerator / 0.0;
    }
    catch(InvalidOperationException ex)
    {
        Console.WriteLine("Invalid operation");
    }
} 

...

try
{
     DbyZ(1.0);
}
catch(Exception ex)
{
    Console.WriteLine("Exception");
}

这一次,输出将是简单的"Exception"。请记住,您不必总是在引发异常的地方捕获异常。

如果您对给定案例中可能发生的情况仍有疑问,请创建自己的样本来测试案例并查看。

【讨论】:

  • 非常感谢您提供的示例。我运行了您的第一个代码示例。系统没有崩溃,但也没有给出任何错误。当我添加代码“throw new DivideByZeroException();”在 try 块中,我收到“尝试除以零”错误消息。
  • 当我在没有“throw new DivideByZeroException();”的情况下运行程序时,程序执行没有进入catch块。当我明确抛出它时,会调用 catch 块并显示错误消息。
  • 检查这个:dotnetfiddle.net/kuXq0R 不知道为什么最后一个样本没有做任何事情。
  • 对持久性表示歉意。请检查一下。它与您的代码相同,但未显示 catch 块消息(甚至不输入 catch 块)dotnetfiddle.net/N67HJ4
  • 我找到了。出于某种原因,除以 0.0(相对于变量 d,它被赋值为 0)不会引发异常。不知道为什么。
【解决方案2】:

操作:

throw new IndexOutofRangeException;

这将甚至编译(没有括号)。

如果您的域中出现意外异常,您应该抛出异常,并且应该在您知道如何处理它们的地方捕获它们。

你写的:

“try 块中有代码产生异常,但是 try 块没有 throw 语句。会发生什么?”。

如果异常类型和模式匹配对应于抛出的异常,则异常将在堆栈中冒泡,并且您的 catch 语句将执行。

【讨论】:

  • 这与我从问题中得到的不同......但我喜欢它!由于 Q 现在较旧,如果我将其作为答案中的另一个示例,您会反对吗?如果你觉得它在窃取你的想法,我就不管它了。
【解决方案3】:

如果代码创建了一个异常但没有抛出它,try/catch 看不到它。抛出异常是唯一使异常不同于任何其他类类型的事情。

.NET 异常是软件工件。尽管其中许多对应于硬件陷阱或操作系统错误,但硬件不会产生、生成或抛出 .NET 异常对象。发生的情况是 .NET 运行时引擎中的代码检测到其他错误,然后创建并抛出一个 .NET 异常对象,将较低级别的错误信息转换为 .NET 异常的属性。

可以以事件驱动的方式调用转换/包装代码,例如通过安装 Windows 结构化异常处理的处理程序,而不是使用代码来测试浮点 NaN 的每个算术结果。但它仍然是软件。作为一个具体的例子,在乔尔的回答中,代码1 / 0.0 不会生成DivideByZeroException。它生成一个 FPU 异常,并且公共语言运行时处理该 FPU 异常。是 CLR 中的处理程序创建并抛出位于您的 catch 块中的 DivideByZeroException 实例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    • 2012-06-28
    • 1970-01-01
    相关资源
    最近更新 更多