处理意外枚举值的首选方法是什么?

2022-09-03 04:06:50

假设我们有一个接受枚举值的方法。此方法检查该值是否有效后,它将超过可能的值。所以问题是,在验证值范围,处理意外值的首选方法是什么?switch

例如:

enum Mood { Happy, Sad }

public void PrintMood(Mood mood)
{
    if (!Enum.IsDefined(typeof(Mood), mood))
    {
        throw new ArgumentOutOfRangeException("mood");
    }

    switch (mood)
    {
        case Happy: Console.WriteLine("I am happy"); break;
        case Sad:   Console.WriteLine("I am sad"); break;
        default: // what should we do here?
    }

处理案件的首选方法是什么?default

  • 发表评论 喜欢// can never happen
  • Debug.Fail()(或Debug.Assert(false))
  • throw new NotImplementedException()(或任何其他例外情况)
  • 其他一些我没有想到的方法

答案 1

我想上面的大多数答案都是有效的,但我不确定任何答案都是正确的。

正确的答案是,你很少切换OO语言,这表明你做错了OO。在这种情况下,这完全表明 Enum 类存在问题。

你应该只调用 Console.WriteLine(mood.moodMessage()),并为每个状态定义 moodMessage。

如果添加了新状态 - 您的所有代码都应自动适应,则不会失败,引发异常或需要更改。

编辑:回复评论。

在您的示例中,要成为“良好的 OO”,文件模式的功能将由 FileMode 对象控制。它可以包含一个具有“打开,读取,写入...”的委托对象。每个FileMode的操作都不同,因此File.open(“name”,FileMode.Create)可以实现为(抱歉不熟悉API):

open(String name, FileMode mode) {
    // May throw an exception if, for instance, mode is Open and file doesn't exist
    // May also create the file depending on Mode
    FileHandle fh = mode.getHandle(name);
    ... code to actually open fh here...
    // Let Truncate and append do their special handling
    mode.setPosition(fh);
}

这比尝试使用开关要整洁得多...(顺便说一句,这些方法既是包私有的,也可能委托给“Mode”类)

当OO做得好时,每个方法看起来都像几行真正可理解的简单代码 - 太简单了。你总会觉得有一些凌乱的大“奶酪核”把所有的小玉米片物体都固定在一起,但你永远找不到它——它一直都是玉米片......


答案 2

我更喜欢.关键是枚举将来可能会更改,并且此方法可能不会相应地更新。引发异常似乎是最安全的方法。throw new NotImplementedException("Unhandled Mood: " + mood)

我不喜欢这种方法,因为该方法可能是库的一部分,并且新值可能不会在调试模式下进行测试。在这种情况下,使用该库的其他应用程序可能会面临奇怪的运行时行为,而在引发异常的情况下,错误将立即被知道。Debug.Fail()

注意:存在于commons.lang中。NotImplementedException