无效泛型类型参数的最佳异常

我目前正在为 无拘无束的旋律编写一些代码,这些代码使用了与枚举有关的通用方法。

Now, I have a static class with a bunch of methods which are 只有 meant to be used with "flags" enums. I can't add this as a constraint... so it's possible that they'll be called with other enum types too. In that case I'd like to throw an exception, but I'm not sure which one to throw.

具体来说,如果我有这样的东西:

// Returns a value with all bits set by any values
public static T GetBitMask<T>() where T : struct, IEnumConstraint
{
if (!IsFlags<T>()) // This method doesn't throw
{
throw new ???
}
// Normal work here
}

最好的例外是什么?ArgumentException听起来合乎逻辑,但它是一个 类型参数,而不是一个正常的参数,这很容易混淆事物。我应该介绍我自己的 TypeArgumentException类吗?使用 InvalidOperationExceptionNotSupportedException?还有别的事吗?

我不会为此创建我自己的异常,除非这显然是正确的事情。

29959 次浏览

我总是对编写自定义异常持谨慎态度,纯粹是因为它们并不总是被清楚地记录下来,如果没有正确地命名,就会造成混乱。

在这种情况下,我会为标志检查失败抛出 ArgumentException。这都取决于你的喜好。我看到的一些编码标准甚至定义了在这样的场景中应该抛出哪些类型的异常。

如果用户试图传入不是枚举的内容,那么我会抛出 InvalidOperationException。

编辑:

其他人提出了一个有趣的观点,即这种观点不受支持。我唯一关心的 NotSupportedException 异常是,一般来说,这些异常是当“暗物质”被引入系统时抛出的,或者换句话说,“这个方法必须在这个接口上进入系统,但是我们直到2.4版才会打开它”

我还看到过 NotSupportedException 作为许可异常被抛出,“您正在运行这个软件的免费版本,这个函数不受支持”。

Edit 2:

另一个可能的解释是:

System.ComponentModel.InvalidEnumArgumentException

使用作为枚举数的无效参数时引发的异常。

我将使用 NotSupportedException,因为这就是您要说的。特定枚举以外的其他枚举是 不支持。当然,在异常消息中会更清楚地说明这一点。

我选择 NotSupportedException。

我会选 NotSupportedException。虽然 ArgumentException看起来没问题,但是当传递给方法的参数不可接受时,就会出现这种情况。类型参数是要调用的实际方法的定义特征,而不是真正的“参数”当您正在执行的操作在某些情况下是有效的时候,应该抛出 InvalidOperationException,但是对于特定的情况,它是不可接受的。

当操作本身不受支持时引发 NotSupportedException。例如,在实现某个接口时,某个特定成员对类没有意义。看起来情况差不多。

从 NotSupportedException 继承怎么样。虽然我同意@Mehrdad 的观点,这是最有意义的,但我听到了你的观点,它似乎并不完全适合。因此从 NotSupportedException 继承,这样针对您的 API 编写代码的人仍然可以捕获 NotSupportedException。

我会避免 NotSupportedException。此异常用于未实现方法的框架中,并且有一个属性指示不支持此类型的操作。这里不合适

我认为 InvalidOperationException 是您可以在这里抛出的最合适的异常。

泛型不应在运行时抛出无效的类型参数。它不应该编译,你应该有一个编译时强制。我不知道 IsFlag<T>()包含什么,但是也许您可以将其转换为编译时实施,比如尝试创建一个只能用“标志”创建的类型。也许一个 traits类可以帮助。

Update

如果你抛出 must,我会投票给 InvalidOperationException。原因是泛型类型具有 参数,与(方法)参数相关的错误围绕 ArgumentException 层次结构居中。但是,ArgumentException 上的 建议指出

如果故障不涉及 那么,他们自己也在争论 InvalidOperationException 应该是 used.

这里至少有一个信念的飞跃,那就是 方法参数建议也应用于 一般参数,但是在 SystemException 层次结构 imho 中没有更好的东西了。

NotSupportedException sounds与它非常匹配,但是文档明确指出它应该用于不同的用途。根据 MSDN 课堂讲话:

有些方法不是 在基类中支持,使用 期望这些方法 在派生类中实现 取而代之。派生类可能 只实现方法的一个子集 从基础类,然后扔 异常 unsupported methods.

当然,在某种程度上,NotSupportedException显然已经足够好了,特别是考虑到它的常识性含义。话虽如此,我不确定这是否正确。

鉴于 无拘无束的旋律的目的..。

有很多有用的东西可以用泛型来完成 方法/类,其中存在“ T: enum”或“ T: 但不幸的是,这在 C # 中是被禁止的。

这个公共图书馆的工作围绕禁止使用伊尔达姆/伊拉姆..。

... 看起来一个新的 Exception可能是有序的,尽管我们必须在创建定制 Exceptions之前满足高举证责任。像 InvalidTypeParameterException这样的东西可能在整个库中都是有用的(或者也许不是——这肯定是一种边缘情况,对吗?).

客户机是否需要能够将此异常与 BCL 异常区分开来?客户机什么时候会不小心使用普通的 enum调用这个函数?你会如何回答 编写自定义异常类时应考虑哪些因素?被接受的答案所提出的问题

Throwing a custom made exception should always be done in any case where it is questionable. A custom exception will always work, regardless of the API users needs. The developer could catch either exception type if he does not care, but if the developer needs special handling he will be SOL.

如果有人感兴趣的话,不久前我在 .NET 异常抛出准则上做了一个(不完整的)基于 框架设计指南第二版。的流程图。

Apparently, Microsoft uses ArgumentException for that, as demonstrated on example of 表达式, Enum. TryParse < > or 元帅 in Exceptions section. I couldn't find any example indicating otherwise, either (despite searching local reference source for TDelegate and TEnum).

因此,我认为可以有把握地假设,至少在 Microsoft 代码中,除了基本的变量参数之外,对无效的泛型类型参数使用 ArgumentException是一种常见的做法。考虑到 docs中的异常描述并不区分这些异常,因此它也没有太大的延伸。

Hopefully it decides the question things once and for all.