C#如何解决非void方法调用始终抛异常方法时无返回值编译错误
解决方案
适配C# 8的最简方案(全版本兼容)
把NoSupport改为泛型方法,返回值类型和运算方法的返回值匹配,直接返回该方法的调用结果即可:
private class Math<T> : IMath<T> { internal static readonly IMath<T> P = Math.P as IMath<T> ?? new Math<T>(); T IMath<T>.Add (T a, T b) => NoSupport(); T IMath<T>.Negate (T a) => NoSupport(); // 修改NoSupport为泛型方法,返回T类型 private static T NoSupport() => throw new NotSupportedException($"no math ops for {typeof(T).Name}"); }
该方案不需要依赖任何高版本特性,所有.NET 框架下都可以正常运行,完全满足消除冗余代码的需求。
如果不想修改NoSupport的签名,也可以在调用后加一行永远不会执行的throw语句,满足编译器检查:
T IMath<T>.Add (T a, T b) { NoSupport(); throw null; // 永远不会执行,仅用于通过编译 }
高版本特性支持(.NET Core 3.0+ / .NET 5+)
针对你提出的三个特性问题,C# 对应有成熟的官方解决方案:
- 标记方法始终抛出异常:可以给
NoSupport方法加上System.Diagnostics.CodeAnalysis命名空间下的[DoesNotReturn]特性,编译器会自动识别该方法永远不会返回,不会再报返回值缺失的错误:[DoesNotReturn] private static void NoSupport() => throw new NotSupportedException($"no math ops for {typeof(T).Name}"); - 标记代码不可达:
[DoesNotReturn]特性会隐式告知编译器,调用该方法后的所有代码都是不可达,不需要额外的语法标记。 - 覆盖编译器返回值检查:C# 没有直接关闭该检查的语法,通过上述两种方式给编译器提供足够的元信息,即可自然通过检查,不需要修改编译规则。
补充说明
如果后续升级到C# 11及以上版本,还可以使用[DoesNotReturnIf]等更灵活的条件返回标记,适配更复杂的分支判断场景。
内容的提问来源于stack exchange,提问作者Jason C
相关产品推荐
相关产品推荐

