【问题标题】:C#: Any way to suppress compiler errors similar to suppressing warning messages?C#:有什么方法可以抑制编译器错误,类似于抑制警告消息?
【发布时间】:2011-06-27 06:24:05
【问题描述】:

我有以下代码会产生编译器错误:

    Boolean IConvertible.ToBoolean(IFormatProvider provider)
    {
        ThrowHelper.ThrowInvalidCast(typeof(MyType), typeof(Boolean));
    }

编译器抱怨并非所有代码路径都返回值。这里的问题是 ThrowHelper 会总是抛出错误。它是一个调用静态方法的静态类。

我知道我可以在ThrowHelper 调用之后用一个愚蠢的“返回真”来满足编译器的要求,但这似乎是不必要的代码。我知道我可以禁止显示警告消息,但是当我尝试使用 SuppressMessageAttribute 时,它并不能阻止编译器抱怨。有什么方法可以仅针对此方法抑制此错误?

【问题讨论】:

    标签: c# compiler-errors error-suppression


    【解决方案1】:

    你可以让 ThrowHelper 中的方法只创建异常,而不是实际抛出它。

    Boolean IConvertible.ToBoolean(IFormatProvider provider)
    {
        throw ThrowHelper.CreateInvalidCast(typeof(MyType), typeof(Boolean));
    }
    

    这也可能导致更好的堆栈跟踪:它将指向 ToBoolean,而不是 ThrowInvalidCast。

    【讨论】:

      【解决方案2】:

      除了修复错误之外,没有其他方法可以抑制错误。

      就其性质而言,错误表明编译器认为它无法生成有效代码。抑制错误的唯一方法是修复它们。只需添加它想要的return 语句,然后在Microsoft Connect 上提出一个问题,表明您认为编译器弄错了。

      但是,我怀疑这是预期的行为,因为编译器不知道您正在调用的方法将始终抛出,并且即使不是不可能,也很难以可预测的方式确定任何可能的调用树(想象一下如果您在以 throw 结束之前调用了 20 个方法链)。

      【讨论】:

      • 在 Connect 上创建项目会浪费时间。对于 C# 中的编译器,无法确定某个方法总是抛出。
      • @0xA3:我同意。我自己添加了一些相关的 cmets。
      • @JeffYates:我又遇到了自己的问题和答案,并对这个答案有了另一个想法……编译器不应该内联调用并意识到它只是抛出异常吗? ThrowHelper.ThrowInvalidCast(typeof(MyType), typeof(Boolean)) 方法位于静态帮助器类中,本身就是一个静态方法...
      • 据我所知,内联是在编译的不同阶段完成的,以检测无法访问的代码。所以编译器仍然不会检测到这一点(正如它没有检测到它的事实所示)。
      • 并非总是如此。一些 C# 错误过于迂腐。 Use of unassigned local variable 'someFloatLocal' 是一个我希望我有时能四处走动的人。我可以看到,我的代码仅在枚举 ivar 是一种特殊情况时才为浮点变量赋值,并且只有我将浮点值用于相同的特定枚举特例。但是编译器显然不能,迫使我要么完全重构我当前的人类逻辑组织的函数,要么通过任意为前面的浮动 分配一个可能无效的值来欺骗编译器(这是我的选择——人类统治,机器流口水)
      【解决方案3】:

      一个简单的大脑练习,为什么请求的功能会导致问题。想象一下ThrowHelper.ThrowInvalidCast 是在某个第 3 方库中定义的。您可能知道该方法总是抛出并告诉编译器,或者一个非常高级的静态分析器可能能够确定该方法总是在编译代码时抛出

      现在其他一些开发人员部署了该库的更新版本。现在该方法并不总是抛出。突然之间,有一种情况是你的方法没有返回路径。只是为了处理这种情况,编译器(或运行时)必须包含一个备份计划,在这种情况下该怎么做。对于可以通过编写正确代码轻松解决的问题,开销相当大。

      更新:理论上,C# 可以扩展为允许没有返回路径的方法。 Eric Lippert 在对 Jon Skeet 的回答 here 的评论中提到了这一点:

      “从不”方法只是一个 void 方法,不允许有可到达的端点或任何返回语句。这解决了编译时的问题。在运行时,验证者有责任确保方法真正正确地实现其返回类型语义;验证者可以类似地确定没有返回指令并且终点不可到达。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-09
        • 1970-01-01
        • 2023-03-22
        • 2022-10-15
        • 2019-05-05
        相关资源
        最近更新 更多