Какое из двух исключений было названо? - PullRequest
7 голосов
/ 17 мая 2010

Если у меня есть подпрограмма, которая может генерировать ArgumentException в двух местах, что-то вроде ...

if (Var1 == null)
{
    throw new ArgumentException ("Var1 is null, this cannot be!");
}

if (Val2  == null)
{
    throw new ArgumentException ("Var2 is null, this cannot be either!");
}

Каков наилучший способ определения в моей процедуре вызова, какое из двух исключений было выброшено?

Или

Я делаю это неправильно?

Ответы [ 10 ]

12 голосов
/ 17 мая 2010

Для этого конкретного сценария вы должны использовать ArgumentNullException и правильно заполнить его свойство ParamName, чтобы знать нулевой аргумент.

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

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

throw new ArgumentException("message", "paramName");

throw new ArgumentNullException("paramName", "message");
11 голосов
/ 17 мая 2010

Передайте имя переменной (Val1, Val2 и т. Д.) Во втором аргументе конструктору ArgumentException. Это становится свойством ArgumentException.ParamName.

4 голосов
/ 17 мая 2010

Ваша вызывающая функция не должна заботиться о том, какая строка вызвала исключение. В любом случае ArgumentException был брошен, и оба должны рассматриваться одинаково.

3 голосов
/ 17 мая 2010

Вы не предоставили достаточно информации, чтобы ответить на ваш вопрос. Очевидный ответ - посмотреть на сообщение об исключении, но я предполагаю, что это не то, что вы ищете.

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

Однако, использование собственного типа исключения - единственный способ гарантировать, что вы перехватываете исключение для определенного обстоятельства . Поскольку ArgumentException является частью фреймворка, возможно, что-то еще, что вы вызываете, может выбросить это, что приведет вас к тому же блоку catch. Если вы создадите свой собственный тип исключения (по одному для обоих или по одному для каждого из сценариев), это предоставит вам способ обработки конкретной ошибки. Конечно, судя по вашему примеру, кажется, что было бы проще просто проверить и посмотреть, является ли Val1 или Val2 нулевым, прежде чем вызывать функцию для начала.

3 голосов
/ 17 мая 2010

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

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

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

3 голосов
/ 17 мая 2010

Используйте конструктор ArgumentException (строка, строка) , чтобы определить, какой параметр был пустым.

if (Var1 == null) {
  throw new ArgumentException ("Var1 is null, this cannot be!","Var1");
}

if (Val2  == null){
  throw new ArgumentException ("Var2 is null, this cannot be either!","Var2");
}
2 голосов
/ 17 мая 2010

Что ж, для ArgumentException, в частности, у вас есть параметр, для которого у аргумента возникла проблема:

throw new ArgumentException("Var1 is null, this cannot be!", "Var1");

В более общем смысле вы обычно делаете что-то вроде использования различных (возможно пользовательских) типов исключенийи тогда вызывающий код может иметь разные блоки перехвата

public class MyCustomException1 : ApplicationException {}
public class MyCustomException2 : ApplicationException {}


try
{
 DoSomething();
}
catch(MyCustomException1 mce1)
{
}
catch(MyCustomException2 mce2)
{
}
catch(Exception ex)
{
}
0 голосов
/ 17 мая 2010

Если это тестовый случай, когда вы хотите убедиться, что отображается правильное сообщение об исключении, я знаю, что NUnit имеет ключевое слово ExpectedMessage для атрибута ExpectedException. В противном случае ArgumentNullException - это ArgumentNullException, и ваше приложение должно относиться к ним одинаково. Если вы хотите больше подробностей, создайте свои собственные классы исключений и используйте их.

Чтобы вы могли проверить следующее:

[ExpectedException(typeof(ArgumentNullException), ExpectedMessage="Var1 is null, this cannot be!"]
public void TestCaseOne {
    ...
}

[ExpectedException(typeof(ArgumentNullException), ExpectedMessage="Var2 is null, this cannot be either!"]
public void TestCaseTwo {
    ...
}
0 голосов
/ 17 мая 2010

При выдаче ArgumentExceptions вы всегда можете включить имя аргумента, вызвавшего исключение (это другой конструктор ).Конечно, я предполагаю, что вы действительно хотите знать, какой из них был нулевым, и в этом случае вам, вероятно, следует использовать ArgumentNullException .

0 голосов
/ 17 мая 2010
try
        {
            //code here
        }
        catch (ArgumentException ae)
        {
            Console.WriteLine(ae.ToString());
        }

В выводе вашей консоли будет указано сообщение, которое вы поместили.

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