无效泛型类型参数的最佳例外

Jon*_*eet 100 c# generics exception

我目前正在为UnconstrainedMelody编写一些代码,它具有与枚举有关的通用方法.

现在,我有一个带有一堆方法的静态类,这些方法只能用于"flags"枚举.我不能将其添加为约束...所以它们也可能会被其他枚举类型调用.在那种情况下,我想抛出异常,但我不确定要抛出哪一个.

只是为了使这个具体,如果我有这样的事情:

// 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
}
Run Code Online (Sandbox Code Playgroud)

投掷的最佳例外是什么?ArgumentException听起来合乎逻辑,但它是一个类型参数,而不是一个普通的参数,这很容易混淆事物.我应该介绍自己的TypeArgumentException课吗?用InvalidOperationException吗?NotSupportedException?还要别的吗?

宁愿不为此创建我自己的例外,除非它显然是正确的事情.

Jef*_*nal 43

NotSupportedException 听起来很明显,但文档明确指出它应该用于不同的目的.从MSDN类备注:

基类中不支持某些方法,期望这些方法将在派生类中实现.派生类可能只实现基类中的方法的子集,并为不支持的方法抛出NotSupportedException.

当然,有一种方法NotSupportedException显然足够好,特别是考虑到它的常识意义.话虽如此,我不确定它是否恰到好处.

鉴于无约束旋律的目的......

使用泛型方法/类可以完成各种有用的事情,其中​​存在"T:enum"或"T:delegate"的类型约束 - 但不幸的是,这些在C#中是禁止的.

这个实用程序库使用ildasm/ilasm解决禁止问题...

...... Exception尽管我们必须在创建自定义之前必须满足高举证据,但似乎新的可能是有序的Exceptions.类似的东西InvalidTypeParameterException可能在整个库中有用(或者可能不是 - 这肯定是一个边缘情况,对吧?).

客户是否需要能够将其与BCL例外区分开来?什么时候客户不小心使用香草调用它enum?您如何回答接受的答案所提出的问题?在编写自定义异常类时应考虑哪些因素?

  • 我要使用TypeArgumentException. (23认同)

Jar*_*Par 23

我会避免使用NotSupportedException.此异常用于未实现方法的框架中,并且存在指示不支持此类操作的属性.它不适合这里

我认为InvalidOperationException是你可以抛出的最合适的异常.


Rem*_*anu 13

对于无效的类型参数,通用编程不应在运行时抛出.它不应该编译,你应该有一个编译时执行.我不知道IsFlag<T>()包含什么,但也许您可以将其转换为编译时执行,例如尝试创建只能使用'flags'创建的类型.也许一traits堂课可以提供帮助.

更新

如果你必须抛出,我会投票给InvalidOperationException.原因是泛型类型具有参数,并且与(方法)参数相关的错误以ArgumentException层次结构为中心.但是,对ArgumentException 的建议说明了这一点

如果失败不涉及参数本身,则应使用InvalidOperationException.

在那里至少有一个信念的飞跃,方法参数建议也应用于通用参数,但SystemException hierachy imho中没有更好的东西.

  • 不,无法在编译时对其进行限制。`IsFlag&lt;T&gt;` 确定枚举是否应用了 `[FlagsAttribute]`,并且 CLR 没有基于属性的约束。它会在一个完美的世界中 - 或者会有其他一些方法来限制它 - 但在这种情况下它不起作用:( (3认同)

Rob*_*ban 9

我会使用NotSupportedException,因为这就是你所说的.不支持除特定枚举之外的其他枚举.当然,这将在异常消息中更清楚地说明.

  • NotSupportedException在BCL中用于非常不同的目的.它不适合这里.http://blogs.msdn.com/jaredpar/archive/2008/12/12/notimplementedexception-vs-notsupportedexception.aspx (2认同)

Meh*_*ari 8

我会去的NotSupportedException.虽然ArgumentException看起来很好,但是当传递给方法的参数是不可接受的时,它确实是预期的.类型参数是您要调用的实际方法的定义特征,而不是真正的"参数".InvalidOperationException当你正在执行的操作在某些情况下有效时应抛出,但对于特定情况,这是不可接受的.

NotSupportedException当操作本身不受支持时抛出.例如,在实现某个特定成员对某个类没有意义的接口时.这看起来像是类似的情况.


Ali*_*ice 6

显然,Microsoft使用ArgumentException了此方法,如“ 例外”部分中的Expression.Lambda <>Enum.TryParse <>Marshal.GetDelegateForFunctionPointer <>的示例所示。我也找不到任何指示相反的示例(尽管在本地参考源中搜索TDelegateTEnum)。

因此,我认为可以安全地假设至少在Microsoft代码中,ArgumentException除了基本变量之外,对无效的泛型类型参数使用通用的做法。鉴于docs中的异常描述不会区分这些异常,因此也没有太大的困难。

希望它能一劳永逸地决定问题。

  • 框架中的单个示例对我来说还不够,不 - 考虑到我认为 MS 在其他情况下做出了糟糕选择的地方的数量:) 我不会从 `ArgumentException` 派生出 `TypeArgumentException`,仅仅因为类型争论不是常规争论。 (2认同)