C #: я должен бросить ArgumentException или NotSupportedException, когда тип аргумента не поддерживается? - PullRequest
1 голос
/ 03 апреля 2019

Итак, у меня возникла ситуация, когда мне нужно выдать исключение, потому что «аргумент не поддерживается».Чтобы объяснить, как я попал сюда, вот грубая ситуация:

  • Уки бывают разных типов, включая Yooks и Zooks
  • Ooks могут подружиться с другими Ooks, но только из правильных типов
  • 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 (подкласс не принимает аргумент), не так ли?

Итак, какой из них я должен выбрать - или я должен написать пользовательское исключениевместо этой ситуации?

Ответы [ 2 ]

0 голосов
/ 04 апреля 2019

Вы не должны бросать ни одно исключение. Вы объявили этот метод:

public bool TryBefriend(Ook o0k)

В нем говорится, что этот метод ожидает аргумент типа Ook. Если кто-то передает аргумент этого типа или одного из его подклассов, и он компилируется, то было бы нехорошо выдать им ошибку времени выполнения и сказать, по сути: «Нет, не тот тип. Я действительно имел в виду это». тип и этот тип, но не тот. "

Если возможно попытаться подружиться с чем-то, но в результате это может или не может быть успешным, то попытка не должна вызывать исключение. Мы не должны использовать исключения как способ управления нормальным, предсказуемым потоком программ.

Думайте об этом, как о попытке вывести деньги из банка. Если вы попытаетесь снять 1000 долларов, вы должны получить сообщение о том, что это удалось или что не удалось, потому что у вас нет 1000 долларов. Он не должен возвращать успех, если у вас достаточно денег, или выкидывать исключение, если у вас его нет. Недостаток денег - нормальная, предсказуемая возможность. Если, с другой стороны, приложение не может продолжить работу, поскольку оно потеряло соединение с базой данных и восстановить его невозможно, тогда было бы целесообразно создать исключение.

Так что я просто вернул бы true или false, и тогда вызывающий абонент может решить, что делать, основываясь на ответе. Вы увидите это, что имеет смысл:

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

... и не это, что неудобно:

try
{
    someOok.TryBefriend(someOtherOook);
    // friends!
}
catch(NotSupportedException ex)
{
    // not friends!
}
0 голосов
/ 03 апреля 2019

В соответствии с MSDN:

NotSupportedException Исключение, которое вызывается, когда вызываемый метод не поддерживается или при попытке чтения, искать или записывать в поток, который не поддерживает вызванную функциональность.

ArgumentException Class Исключение, которое выдается, когда один из предоставленных аргументовметод недопустим

Таким образом, в соответствии с MSDN, ArgumentException больше подходит для редактирования вашего случая: если абсолютно необходимо больше аргументов или пользовательский возврат, вы можете написать собственное пользовательское исключениеТем не менее, нет никаких проблем в использовании ArgumentException, если он соответствует вашим потребностям.

...