用于处理不返回的非 void 方法的 C# 选项

标签 c# exception c#-8.0

我有一个 this answer 的实现 在我的一些代码中,如:

private interface IMath<T> {
    internal T Add (T value1, T value2);
    internal T Negate (T value);
}

private class Math<T> : IMath<T> {
    internal static readonly IMath<T> P = Math.P as IMath<T> ?? new Math<T>();
    // !!! My question concerns this portion of code:
    T IMath<T>.Add (T a, T b) { NoSupport(); }
    T IMath<T>.Negate (T a) { NoSupport(); }
    private static void NoSupport () =>
        throw new NotSupportedException($"no math ops for {typeof(T).Name}");
    // !!! End code-of-interest.
}

private class Math : IMath<int>, IMath<float> {
    internal static Math P = new Math();
    int IMath<int>.Add (int a, int b) { return a + b; }
    int IMath<int>.Negate (int value) { return -value; }
    float IMath<float>.Add (float a, float b) { return a + b; }
    float IMath<float>.Negate (float value) { return -value; }
}

意图所在,例如:

static T Negate <T> (T v) => Math<T>.P.Negate(v);

// elsewhere...
_ = Negate(3);    // ok (int)
_ = Negate(3.0f); // ok (float) 
_ = Negate(3.0);  // throws NotSupportedException (double)

那个 NoSupport() 函数是我遇到的问题。我只是添加它来处理针对不支持的类型抛出异常和消息,并在添加更多操作时尝试保持代码简单。

但是,它无法编译 (C# 8),并在两个方法(AddNegate)中出现预期的“并非所有控制路径都返回值”错误调用它。

我明白这一点,我也明白为什么它不能编译,这是有道理的。但是,那么,我怎样才能实现既让代码简单方便又满足编译器的目标呢?

从我迄今为止所做的研究来看,似乎没有一种方法可以明确指定一个方法不返回,但我想知道是否有一种方法可以...

  • ...指定 NoSupport() 始终抛出异常?或者...
  • ...将一行代码标记为无法访问(例如,在调用 NoSupport() 之后)?或者...
  • ...将方法标记为始终实际返回值(覆盖编译器的分析)?

我的主要目标是消除冗余代码(即我对其他方法持开放态度),我的次要目标是了解 C# 处理所有路径都返回值的方法的特定选项即使编译器看不到它(有什么选择吗?)。

我有一种感觉,有一种非常简单的方法,但我现在只见树木不见森林。

最佳答案

最简单的解决方案是将 NoSupport() 从 void 更改为 T

因此成为:

    T IMath<T>.Add (T a, T b) => NoSupport();
    T IMath<T>.Negate (T a) => NoSupport();
    private static T NoSupport () =>
        throw new NotSupportedException($"no math ops for {typeof(T).Name}");

此外,您还可以使用 CallerMemberNameAttribute 为错误消息增添一些趣味。其中将自动包含调用 NotSupport 的方法的名称。

    T IMath<T>.Add (T a, T b) => NoSupport(); //will throw "Add not supported"
    T IMath<T>.Negate (T a) => NoSupport();   //will throw "Negate not supported"
    private static T NoSupport ([CallerMemberName] string method = "") =>
        throw new NotSupportedException($"{method} not supported.");

关于用于处理不返回的非 void 方法的 C# 选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67765919/

相关文章:

c# - 我可以在 RESTful 服务中使用 TCP 吗?

c# - 如何扩展 WinForm 的 Dispose 方法?

c# - EF 4.1/Linq-to-SQL : What is better: using Equals or ==?

java - 音频文件转码期间出现编码异常

c# - 有没有一种方法可以让 switch 使用 C# 8 switch 表达式返回字符串值?

c# - 从 EF6 模型自动生成的 TT 文件渲染默认参数说明符不允许错误

Python异常离开本地范围?

Java:从数组中划分对

c# - 自动属性的默认接口(interface)方法和默认值

c# - 在 C# 8 中,为什么对新表达式的类型推断会导致可空引用?