C# 无效泛型类型参数的最佳例外
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1412598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best exception for an invalid generic type argument
提问by Jon Skeet
I'm currently writing some code for UnconstrainedMelodywhich has generic methods to do with enums.
我目前正在为UnconstrainedMelody编写一些代码,它具有与枚举有关的通用方法。
Now, I have a static class with a bunch of methods which are onlymeant 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.
现在,我有一个带有一堆方法的静态类,这些方法仅用于“标志”枚举。我无法将其添加为约束...因此也有可能使用其他枚举类型调用它们。在这种情况下,我想抛出一个异常,但我不确定要抛出哪个异常。
Just to make this concrete, if I have something like this:
只是为了具体说明,如果我有这样的事情:
// 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
}
What's the best exception to throw? ArgumentException
sounds logical, but it's a typeargument rather than a normal argument, which could easily confuse things. Should I introduce my own TypeArgumentException
class? Use InvalidOperationException
? NotSupportedException
? Anything else?
抛出的最佳异常是什么?ArgumentException
听起来合乎逻辑,但它是一个类型参数而不是普通参数,这很容易混淆。我应该介绍我自己的TypeArgumentException
班级吗?使用InvalidOperationException
? NotSupportedException
? 还要别的吗?
I'd rathernot create my own exception for this unless it's clearly the right thing to do.
我宁愿不为此创建自己的例外,除非这显然是正确的做法。
采纳答案by Jeff Sternal
NotSupportedException
soundslike it plainly fits, but the documentation clearly states that it should be used for a different purpose. From the MSDN class remarks:
NotSupportedException
听起来很合适,但文档明确指出它应该用于不同的目的。来自 MSDN 课堂评论:
There are methods that are not supported in the base class, with the expectation that these methods will be implemented in the derived classes instead. The derived class might implement only a subset of the methods from the base class, and throw NotSupportedException for the unsupported methods.
有些方法在基类中不受支持,但期望这些方法将在派生类中实现。派生类可能只实现基类方法的一个子集,并为不受支持的方法抛出 NotSupportedException。
Of course, there's a way in which NotSupportedException
is obviously good enough, especially given its common-sense meaning. Having said that, I'm not sure if it's just right.
当然,有一种方式NotSupportedException
显然已经足够好了,尤其是考虑到它的常识意义。话虽如此,我不确定它是否正确。
Given the purpose of Unconstrained Melody...
鉴于无约束旋律的目的......
There are various useful things that can be done with generic methods/classes where there's a type constraint of "T : enum" or "T : delegate" - but unfortunately, those are prohibited in C#.
This utility library works around the prohibitions using ildasm/ilasm ...
使用泛型方法/类可以完成各种有用的事情,其中存在“T:枚举”或“T:委托”的类型约束——但不幸的是,这些在 C# 中是被禁止的。
这个实用程序库使用 ildasm/ilasm ...
... it seems like a new Exception
might be in order despite the high burden of proof we justly have to meet before creating custom Exceptions
. Something like InvalidTypeParameterException
might be useful throughout the library (or maybe not - this is surely an edge case, right?).
......Exception
尽管我们在创建自定义之前必须满足高举证责任,但似乎新的可能是有序的Exceptions
。类似的东西InvalidTypeParameterException
可能在整个库中都有用(或者可能不是 - 这肯定是一个边缘情况,对吧?)。
Will clients need to be able to distinguish this from BCL Exceptions? When might a client accidentally call this using a vanilla enum
? How would you answer the questions posed by the accepted answer to What factors should be taken into consideration when writing a custom exception class?
客户是否需要能够将其与 BCL 异常区分开来?客户什么时候可能会使用 vanilla 不小心调用它enum
?您将如何回答在编写自定义异常类时应考虑哪些因素的公认答案所提出的问题?
回答by Peter
I'm always wary of writing custom exceptions, purely on the grounds that they aren't always documented clearly and cause confusion if not named correctly.
我总是对编写自定义异常持谨慎态度,纯粹是因为它们并不总是被清楚地记录下来,如果命名不正确会导致混乱。
In this case I would throw an ArgumentException for the flags check failure. It's all down to preference really. Some coding standards I've seen go as far as to define which types of exceptions should be thrown in scenarios like this.
在这种情况下,我会为标志检查失败抛出 ArgumentException。这完全取决于偏好。我见过的一些编码标准甚至定义了在这样的场景中应该抛出哪些类型的异常。
If the user was trying to pass in something which wasn't an enum then I would throw an InvalidOperationException.
如果用户试图传入不是枚举的东西,那么我会抛出一个 InvalidOperationException。
Edit:
编辑:
The others raise an interesting point that this is not supported. My only concern with a NotSupportedException is that generally those are the exceptions that get thrown when "dark matter" has been introduced to the system, or to put it another way, "This method must go into the system on this interface, but we won't turn it on until version 2.4"
其他人提出了一个有趣的观点,即这不受支持。我对 NotSupportedException 唯一关心的是,通常那些是在系统中引入“暗物质”时抛出的异常,或者换句话说,“这个方法必须在这个接口上进入系统,但我们赢了在 2.4 版之前不要打开它”
I've also seen NotSupportedExceptions be thrown as a licensing exception "you're running the free version of this software, this function is not supported".
我还看到 NotSupportedExceptions 被作为许可异常抛出“您正在运行此软件的免费版本,不支持此功能”。
Edit 2:
编辑2:
Another possible one:
另一种可能:
System.ComponentModel.InvalidEnumArgumentException
The exception thrown when using invalid arguments that are enumerators.
使用枚举数的无效参数时抛出的异常。
回答by Robban
I would use NotSupportedException as that is what you are saying. Other enums than the specific ones are not supported. This would of course be stated more clearly in the exception message.
我会使用 NotSupportedException ,因为这就是你所说的。不支持特定枚举以外的其他枚举。这当然会在异常消息中更清楚地说明。
回答by Carl Bergquist
Id go with NotSupportedExpcetion.
Id 与 NotSupportedExpcetion 一起使用。
回答by Mehrdad Afshari
I'd go with NotSupportedException
. While ArgumentException
looks fine, it's really expected when an argument passed to a method is unacceptable. A type argument is a defining characteristic for the actual method you want to call, not a real "argument." InvalidOperationException
should be thrown when the operation you're performing can be valid in some cases but for the particular situation, it's unacceptable.
我会去的NotSupportedException
。虽然ArgumentException
看起来不错,但当传递给方法的参数不可接受时,确实是预料之中的。类型参数是您要调用的实际方法的定义特征,而不是真正的“参数”。InvalidOperationException
应该在您执行的操作在某些情况下有效时抛出,但对于特定情况,这是不可接受的。
NotSupportedException
is thrown when an operation is inherently unsupported. For instance, when implementing an interface where a particular member doesn't make sense for a class. This looks like a similar situation.
NotSupportedException
当操作本身不受支持时抛出。例如,当实现一个特定成员对类没有意义的接口时。这看起来是类似的情况。
回答by BFree
How about inheriting from NotSupportedException. While I agree with @Mehrdad that it makes the most sense, I hear your point that it doesn't seem to fit perfectly. So inherit from NotSupportedException, and that way people coding against your API can still catch a NotSupportedException.
如何从 NotSupportedException 继承。虽然我同意 @Mehrdad 的观点,认为它最有意义,但我听到你的观点,它似乎并不完美。因此,从 NotSupportedException 继承,这样人们对您的 API 进行编码仍然可以捕获 NotSupportedException。
回答by JaredPar
I would avoid NotSupportedException. This exception is used in the framework where a method is not implemented and there is a property indicating that this type of operation is not supported. It doesn't fit here
我会避免 NotSupportedException。此异常用于未实现方法且有属性指示不支持此类操作的框架中。这里不适合
- Shameless self Reference: http://blogs.msdn.com/jaredpar/archive/2008/12/12/notimplementedexception-vs-notsupportedexception.aspx
- 无耻的自我参考:http: //blogs.msdn.com/jaredpar/archive/2008/12/12/notimplementedexception-vs-notsupportedexception.aspx
I think InvalidOperationException is the most appropriate exception you could throw here.
我认为 InvalidOperationException 是您可以在这里抛出的最合适的异常。
回答by Remus Rusanu
Generic programming should not throw at runtime for invalid type parameters. It should not compile, you should have a compile time enforcement. I don't know what IsFlag<T>()
contains, but perhaps you can turn this into a compile time enforcement, like trying to create a type that is only possible to create with 'flags'. Perhaps a traits
class can help.
泛型编程不应在运行时抛出无效类型参数。它不应该编译,你应该有一个编译时强制执行。我不知道IsFlag<T>()
包含什么,但也许您可以将其转换为编译时强制执行,例如尝试创建只能使用“标志”创建的类型。也许一个traits
班级可以提供帮助。
Update
更新
If you mustthrow, I'd vote for InvalidOperationException. The reasoning is that generic types have parametersand errors related to (method) parameters are centered around the ArgumentException hierarchy. However, the recommendationon ArgumentException states that
如果你必须抛出,我会投票给 InvalidOperationException。原因是泛型类型具有参数,并且与(方法)参数相关的错误以 ArgumentException 层次结构为中心。但是,关于 ArgumentException的建议指出
if the failure does not involve the arguments themselves, then InvalidOperationException should be used.
如果失败不涉及参数本身,则应使用 InvalidOperationException。
There is at least one leap of faith in there, that methodparameters recommendations are also to be applied to genericparameters, but there isn't anything better in the SystemException hierachy imho.
那里至少有一个信念的飞跃,方法参数建议也适用于泛型参数,但在 SystemException 层次结构中没有什么比 imho 更好的了。
回答by Eric Schneider
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.
在任何有问题的情况下,都应始终抛出自定义异常。无论 API 用户需要什么,自定义异常始终有效。如果开发人员不在乎,他可以捕获任何一种异常类型,但如果开发人员需要特殊处理,他将成为 SOL。
回答by TrueWill
I'd also vote for InvalidOperationException. I did an (incomplete) flowchart on .NET exception throwing guidelinesbased on Framework Design Guidelines 2nd Ed.awhile back if anyone's interested.
我也会投票给 InvalidOperationException。我根据框架设计指南第 2 版在.NET 异常抛出指南上做了一个(不完整的)流程图。如果有人感兴趣,请稍后返回。