【问题标题】:C#: should I throw an ArgumentException or NotSupportedException when an argument type is not supported?C#:当不支持参数类型时,我应该抛出 ArgumentException 还是 NotSupportedException?
【发布时间】:2019-08-25 10:32:06
【问题描述】:

所以,我遇到了需要抛出异常的情况,因为“不支持参数”。为了解释我是如何到达这里的,这是粗略的情况:

  • Ook 有多种类型,包括 Yook 和 Zooks
  • Ook 可以与其他 Ook 成为朋友,但只能是正确的类型
  • Yooks 可以与 Zooks 交朋友,但 Zooks 不能与 Yooks 交朋友

代码示例:

public abstract class Ook
{
    public abstract bool TryBefriendYook(Yook yook);
    public abstract bool TryBefriendZook(Zook zook);

    public bool TryBefriend(Ook o0k)
    {
        Type ookType = ook.GetType;

        if (ookType == typeof(Yook))
        {
            TryBefriendYook((Yook)ook);
            return true;
        }
        else if (ookType == typeof(Zook))
        {
            TryBefriendZook((Zook)ook);
            return true;
        }
        else return false;
    }

    public void Befriend(Ook ook)
    {
        if(!TryBefriend(ook))
            throw new Exception(
                "argument type not supported");
    }
}

public sealed class Yook : Ook
{
    public override bool TryBefriendYook(Yook yook)
    {
        return true;
    }
    public override bool TryBefriendZook(Zook zook)
    {
        return true;
    }
}

public partial sealed class Zook : Ook
{
    public override bool TryBefriendYook(Yook yook)
    {
        return false;
    }
    public override bool TryBefriendZook(Zook zook)
    {
        return true;
    }
}

所以,这种类型属于ArgumentException(该参数不适用于子类)和NotSupportedException(子类不接受该参数),不是吗?

那么,我应该选择哪一个 - 或者我应该为这种情况编写一个自定义异常?

【问题讨论】:

  • NotSupportedException 在不支持调用的方法时被抛出,msdn 描述了这些情况。 ArgumentException或者你自己的更适合这里
  • 您有什么理由要使用特定类型的异常吗?
  • @PavelAnikhouski 在这种情况下,Zook.BefriendYook 不受支持。这与 msdn 列出的第一个示例几乎完全相同。 @TheDon 你总是应该抛出最具体的异常,并且永远抛出普通的System.Exception

标签: c# polymorphism custom-exceptions argumentexception notsupportedexception


【解决方案1】:

您不应该抛出任何异常。你已经声明了这个方法:

public bool TryBefriend(Ook o0k)

它说这个方法需要一个Ook 类型的参数。如果有人传递了一个属于该类型或其子类之一的参数,并且它可以编译,那么给他们一个运行时错误并说,实际上,“不,不是那种类型。我真的是这个意思type 和 this type,但不是那个。”

如果有可能尝试与某物交朋友,但结果是它可能成功也可能不成功,那么尝试不应该抛出异常。我们不应该使用异常来管理正常的、可预测的程序流。

把它想象成试图从银行取款。如果您尝试提取 1000 美元,您应该会收到一条消息说成功或失败,因为您没有 1000 美元。如果您有足够的钱,它不应该返回成功,如果没有,则抛出异常。没有足够的钱是正常的,可预测的可能性。另一方面,如果应用程序因为失去数据库连接而无法继续运行并且无法恢复,那么抛出异常是有意义的。

所以我只返回truefalse,然后调用者可以根据响应决定做什么。你会看到这个,这是有道理的:

if(someOok.TryBefriend(someOtherOook))
{
    // friends!
}
else
{
    // not friends!
}

...而不是这个,这很尴尬:

try
{
    someOok.TryBefriend(someOtherOook);
    // friends!
}
catch(NotSupportedException ex)
{
    // not friends!
}

【讨论】:

    【解决方案2】:

    根据 MSDN:

    NotSupportedException 当调用的方法不受支持,或者尝试读取、查找或写入不支持调用的功能的流时引发的异常。

    ArgumentException Class提供给方法的参数之一无效时引发的异常

    所以根据 MSDN,ArgumentException 更适合您的情况 编辑:如果绝对需要更多参数或自定义返回,您可以编写自己的自定义异常,但是如果符合您的需要,使用 ArgumentException 没有问题。

    【讨论】:

    • 问题在于,这也是不支持调用的方法时(即Zook.BefriendYook的情况
    • @TravisReed:Befriend 的调用者没有调用不受支持的方法。您对Befriend 的实现做到了这一点。不要抛出异常来让调用者处理你的实现中的错误。 (但实际上,您对Zook.TryBefriendYook 的调用得到了支持,并正确告诉您尝试失败)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-27
    • 1970-01-01
    • 2012-05-01
    相关资源
    最近更新 更多