为了账号安全,请及时绑定邮箱和手机立即绑定

为什么编译器没有检测到这里会抛出异常?

为什么编译器没有检测到这里会抛出异常?

C#
陪伴而非守候 2023-08-13 16:03:37
我试图将异常抛出逻辑包装到另一个类中,以便更容易抛出自定义异常。每个类都将使用对此 Thrower 类的直接引用或接口,无论哪种最合适。我编写了一个简单的类来处理它并且它在大多数情况下都可以工作,但是我在具有返回类型的方法中遇到了一种情况,即使总是抛出异常,编译器也无法检测到它并抱怨并非所有路径返回一个值。以下代码显示了 Thrower 类和任何使用所述 Thrower 的类的结构的简化形式。public class Thrower{    public void ThrowException()    {        throw new Exception("Im an exception");    }}public class Foo{    // Does not work, compiler complains about not all paths returning values.    public int ExceptionNotDetected(bool shouldThrow)    {        if (!shouldThrow)        {            return 1;        }        var thrower = new Thrower();        thrower.ThrowException();    }    // Works fine.    public int ExceptionDetected(bool shouldThrow)    {        if (!shouldThrow)        {            return 1;        }        throw new Exception("Im an exception");    }}据我所知,使用 Thrower 的方法必须返回一个值或抛出异常。由此看来,ExceptionNotDetected 和 ExceptionDetected 方法在功能上是等效的。那么为什么编译器会抱怨 ExceptionNotDetected 呢?编辑:关于设计,这纯粹是为了说明目的,因为我真正想做的就是了解发生了什么。如果我没有在帖子描述中正确澄清这一点,我深表歉意。话虽这么说,我很欣赏有关结构的建议。
查看完整描述

3 回答

?
慕容森

TA贡献1853条经验 获得超18个赞

编译器只能看到当前方法的返回类型,“ThrowExeption()”方法什么也不返回(void)。

它不会检查被调用方法的内部以查看是否会返回异常。


查看完整回答
反对 回复 2023-08-13
?
一只萌萌小番薯

TA贡献1795条经验 获得超7个赞

由于 C# 不像 Java 那样具有检查异常,因此编译器无法知道抛出者实际上抛出了异常。


但你可以颠倒逻辑


 if (shouldThrow)

    {

    var thrower = new Thrower();

    thrower.ThrowException();

    }

    return 1;

这样,编译器将假设返回 1,并且 ThrowException 方法是一个常规 void,它像任何其他 void 方法一样可能会抛出异常。


查看完整回答
反对 回复 2023-08-13
?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

很简单,因为编译器不会分析函数内部的代码来检测该函数是否总是抛出异常。

C# 似乎没有“永不返回”的属性。

而且,没有理由这样编写代码:

  1. 如果异常类型非常具体,您应该使用不同的异常类型。因此,您将通过调用来抛出它throw new MyExceptionType(my_parameters);

  2. 如果创建稍微复杂一些,那么您可以向类中添加一个静态方法来创建异常对象:throw new MyExceptionType::CreateFromThatData(…);

  3. 如果仅从单个类引发异常,则该类中可能有一个静态函数来创建适当的异常对象。这样,您可以根据某些条件返回不同的异常类型。所有 C# 异常都源自Exception.

  4. 如果您确实想要一个异常工厂,那么static class使用一些(静态)方法来创建所需的异常可能会起作用。

  5. 在您的代码中,我确实没有看到创建对象thrower然后调用它的方法来引发异常的意义。您知道需要 2 行代码来引发异常,而不是一行。

  6. 将调用隐藏throw在函数内会使代码更难以理解和验证。thrower.ThrowException确实抛出异常以及是哪一个异常。

  7. 正如其他答案所示,您可以首先放置引发异常的方法调用,这样编译器就不会报告某些部分不返回值。

您的设计和代码过于复杂,因此产生的问题比解决的问题还要多。


查看完整回答
反对 回复 2023-08-13
  • 3 回答
  • 0 关注
  • 114 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信