【问题标题】:C# options for dealing with non-void methods that don't return用于处理不返回的非 void 方法的 C# 选项
【发布时间】:2021-05-30 21:21:18
【问题描述】:

我在我的一些代码中实现了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() 函数是我遇到的问题。我只是添加它来处理不支持的类型引发异常和消息,以在添加更多操作时尽量保持代码简单。

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

我明白这一点,我明白为什么它没有编译,这是有道理的。但是,那么,我怎样才能实现我的目标,即在这里保持代码简单方便,同时又能满足编译器的要求呢?

从我目前所做的研究来看,似乎没有办法指定一个方法不会返回,但我想知道是否有办法...

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

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

我有一种感觉,有一种非常直接的方法,我现在只能只见树木不见森林。

【问题讨论】:

  • 我猜你可以让 NoSupport() 返回 T 并在方法本身中返回 default(T)。这够简单吗?
  • @JackT.Spades 哦!哇,这太明显了。是的,这正是我接下来要做的,甚至更好的是,我实际上不必从NoSupport() 返回任何东西,因为编译器不会抱怨那里的throw。例如:T NoSupport () =&gt; throw ...;,每个方法都简单地变成T Add(...) =&gt; NoSupport();。谢谢!!您可以根据需要发布答案(但请注意:如果我的问题被 dv'd 搞砸了,嘿,这可能是附带损害)。

标签: c# exception c#-8.0


【解决方案1】:

最简单的解决方案是将 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.");

【讨论】:

  • 非常好,worked like a charm 和超级简单(我真的很喜欢我的尝试,呵呵),再次感谢!!
  • (哦,回复:您的编辑,是的,我肯定会在该错误消息上添加一些调味料,好电话。)
猜你喜欢
  • 2015-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-25
  • 2014-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多