Почему нет ArgumentEmptyException в .NET? - PullRequest
2 голосов
/ 01 июня 2010

Я начинаю думать, что делаю что-то не так. Я имею в виду, что они, наконец, поместили System.String.IsNullOrWhitespace, но без класса ArgumentEmptyException.

        public FilterItem(string name, IEnumerable<string> extensions)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentNullException("name");
            }
            if (extensions == null)
            {
                throw new ArgumentNullException("extensions");
            }
            if (extensions.Count() == 0)
            {
                throw new ArgumentOutOfRangeException("extensions");
            }

            this.Name = name;
            this.Extensions = extensions;
        }

создание исключения ArgumentOutOfRangeException кажется неестественным. Также, на мой взгляд, экземпляр ArgumentException является слишком общим.

Мне легко создать новый класс исключений, назвать его таким образом и покончить с этим. Что меня беспокоит, так это то, что его нет в BCL / FCL, и я начинаю думать, что есть веская причина не иметь его.

Должен ли он быть?

Ответы [ 4 ]

9 голосов
/ 01 июня 2010

Лично я бы просто поднял ArgumentException и добавил бы некоторую информацию в сообщение. Это сообщение просто для того, чтобы помочь вам диагностировать проблемы во время разработки - в действительности не существует ситуации, в которой вы бы хотели перехватить эту ошибку в готовой системе, поэтому нет никаких причин делать ее уникальной catch -able.

4 голосов
/ 02 июня 2010

Есть прецеденты для броска ArgumentNullException в случае String.IsNullOrEmpty - например, System.Windows.Forms.Clipboard.SetText. См. Также этот связанный вопрос .

Таким образом, я думаю, что разумно сделать то же самое для String.IsNullOrWhitespace. ArgumentOutOfRangeException также является разумным выбором, но лично я бы использовал его только тогда, когда аргумент ожидает более ограниченный диапазон значений, чем просто непустой.

Преимущества повторного использования ArgumentNullException (или ArgumentOutOfRangeException) вместо ArgumentException или пользовательского типа исключения:

  • ArgumentNullExceptionArgumentOutOfRangeException) имеет конструктор, который принимает string paramName - поэтому нет необходимости генерировать сообщение, как если бы вы с ArgumentException.

  • Нет необходимости в дополнительной работе по созданию пользовательского типа исключения.

Единственный недостаток, который я вижу, заключается в том, что вызывающему абоненту необходимо обработать это исключение иначе, чем случай null, что мне кажется крайне маловероятным, и если его довести до логического завершения, это приведет к явному перегибу:

if (param == null) throw new ArgumentNullException("param");
if (param.Length == 0) throw new ArgumentEmptyException("param");
if (param.Trim().Length == 0) throw new ArgumentWhitespaceException("param");

Обычно я бы выбрал ArgumentNullException, как я бы интерпретировал следующее руководство MSDN :

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

4 голосов
/ 01 июня 2010

Вы должны просто использовать ArgumentOutOfRange для этого. Ведь его документация гласит:

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

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

Кстати, поскольку вы уже используете .NET 4, почему бы просто не использовать контракты по коду? На самом деле нет особого смысла определять уникальные типы исключений для тех исключений, которые, по сути, являются нарушениями контракта - они никогда не должны быть обнаружены ...

2 голосов
/ 02 июня 2010

Определение новых типов исключений в большинстве случаев должно выполняться только для исключений, которые должны быть перехвачены. В этом случае вы не хотите, чтобы кто-нибудь поймал исключение (вы должны редко ловить ArgumentException s), поэтому нет смысла создавать новое исключение.

В этом случае вы должны выбрать тип исключения, который лучше всего описывает ваше исключение. Я не верю, что это ArgumentOutOfRangeException, потому что трудно увидеть строку как-то «варьируемую». Ваш лучший выбор - ArgumentException, а тип описывает, что не так (аргумент).

Иногда бывает полезно определить новый тип исключения, даже если никто не намеревается его перехватить. В библиотеке CuttingEdge.Conditions я определил PostconditionException только потому, что выбрасывание ArgumentException показалось неправильным при проверке постусловий.

Для разработчиков фреймворка определение новых исключений (которые не должны попадать в ловушку) иногда может быть полезным, поскольку позволяет лучше сообщать о том, что пошло не так. Тем не менее, работая над бизнес-приложениями, я едва ли определяю исключения, которые я не хочу, чтобы кто-то ловил. Я просто использую существующие исключения.

КСТАТИ. При использовании CuttingEdge.Conditions ваш пример кода может быть переписан следующим образом:

public FilterItem(string name, IEnumerable<string> extensions)
{
    Condition.Requires(name, "name").IsNotNullOrWhiteSpace();
    Condition.Requires(extensions, "extensions").IsNotEmpty();

    this.Name = name;
    this.Extensions = extensions;
}

Последнее примечание, я бы переписал последнюю строку кода следующим образом:

    this.Extensions = extensions.ToArray();

Потому что, когда вы требуете, чтобы коллекция была не пустой, вы не хотите, чтобы кто-либо очищал ее после того, как проверил это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...