Должен ли я создавать исключение из этого метода?

Я выполняю некоторую проверку параметров в методе и при необходимости выбрасываю исключение. Нужно ли мне вручную создавать исключения этого типа? Пока вызывающий объект заключен в блок try..catch, аналогичное исключение генерируется независимо от того, выполняются ли ручные проверки.

    public static Int16 ToInt16(this byte[] value, int startIndex, bool isBigEndian) {

        // are these exceptions necessary?
        if (value == null) {
            throw new ArgumentNullException("value");
        }

        if ((startIndex + 1) >= value.Length) {
            throw new ArgumentOutOfRangeException("startIndex");
        }    

        return (isBigEndian)
            ? (Int16)((value[startIndex] << 8) | value[startIndex + 1])
            : (Int16)((value[startIndex + 1] << 8) | value[startIndex]);
    }

Это метод расширения, используемый для преобразования 2 байтов в массиве в Int16 со способом переключения преобразования Big Endian или Little Endian.


person user158485    schedule 30.08.2009    source источник
comment
Обратите внимание, что вы создаете оба исключения только с ParamName, попробуйте придумать полезное сообщение.   -  person Henk Holterman    schedule 30.08.2009
comment
Все, спасибо за комментарии. Кажется, все согласны с тем, что исключения должны оставаться. Я принял ответ Питера, так как он скользнул первым, а также нашел мою опечатку.   -  person user158485    schedule 31.08.2009


Ответы (5)


Ценность создания исключений здесь заключается в том, что вместо получения исключения null deref вы получите исключение аргумента, которое, что наиболее важно, сообщает вам, что аргумент недействителен. Исключение также более явно указывает на причину, чем общий null deref, который может быть чем угодно.

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

Я не знаю, как сейчас, но в платформах .Net 1.1 и 1.0 компилятор JIT никогда не будет встраивать вызов, в котором есть бросок. Избежать этого часто означало бы создать другой метод, который сам выдавал бы исключение.

Кстати у вас офф на одну ошибку с startIndex + 1 > value.Length; вместо этого должно быть >=.

person Peter Oehlert    schedule 30.08.2009

В соответствии с рекомендациями по проектированию библиотеки классов вы должны проверять все параметры общедоступных членов ваших типов. http://msdn.microsoft.com/en-us/library/8ey5ey87(VS.71).aspx


ОБНОВЛЕНИЕ: более новая версия: http://msdn.microsoft.com/en-us/library/ms229007.aspx

person Alfred Myers    schedule 30.08.2009

Если вы посмотрите на код DotNET Framework (скажем, с использованием Reflector), то обнаружите, что ребята из MS вручную выбрасывают эти исключения.

Если вы создаете SDK, который будет активно использоваться сторонними программистами, я рекомендую создавать исключения ArgumentNullException по крайней мере для функций верхнего уровня.

person David Rutten    schedule 30.08.2009

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

Джо

person Community    schedule 30.08.2009

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

Если бы у вас было два метода, MethodA(int i) и MethodB(int i), какой из них легче понять?

  • Метод A(1000) выдает ArgumentOutOfRangeException
  • Метод B(1000) выдает IndexOutOfRangeException

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

person Cameron MacFarland    schedule 30.08.2009
comment
Проблема с таким мышлением заключается в том, что ArgumentOutOfRangeException также мог быть вызван методом, вызванным из MethodA, по причинам, не связанным с аргументом, переданным в methodA, а IndexOutOfRangeException более точно описывает реальную проблему. Что действительно необходимо, так это способ различения просачивающихся исключений, которые не имеют ничего общего с методом, с помощью которого они просачиваются, но для этого нет стандартного соглашения. - person supercat; 03.05.2014