ArgumentException или ArgumentNullException для строковых параметров?
В лучшем случае лучше, чем лучше:
public void SomeMethod(string str)
{
if(string.IsNullOrEmpty(str))
{
throw new ArgumentException("str cannot be null or empty.");
}
// do other stuff
}
или
public void SomeMethod(string str)
{
if(str == null)
{
throw new ArgumentNullException("str");
}
if(str == string.Empty)
{
throw new ArgumentException("str cannot be empty.");
}
// do other stuff
}
Вторая версия кажется более точной, но также более громоздкой, чем первая. Я обычно иду с №1, но решил, что я проверил бы, есть ли аргумент для №2.
Ответы
Ответ 1
Я бы сказал, что второй способ действительно более точный - да, это более громоздко, но вы всегда можете обернуть его методом, чтобы избежать необходимости делать это все время. Это может быть даже метод расширения:
str.ThrowIfNullOrEmpty("str");
public static void ThrowIfNullOrEmpty(this string value, string name)
{
if (value == null)
{
throw new ArgumentNullException(name);
}
if (value == "")
{
throw new ArgumentException("Argument must not be the empty string.",
name);
}
}
Другая потенциально полезная форма - это та, которая возвращает исходную строку, если все в порядке. Вы могли бы написать что-то вроде этого:
public Person(string name)
{
this.name = name.CheckNotEmpty();
}
Другой вариант, который следует рассмотреть, заключается в использовании Code Contracts в качестве альтернативы выбросу собственных исключений.
Ответ 2
Я бы предложил использовать первый. Если ваш метод не ожидает нулевой или пустой строки, то действительно не имеет значения, было ли передано значение null или empty - важно сообщить об ошибке и это то, что делает 1-й вариант.
Ответ 3
Другая возможность - исключение ArgumentOutOfRange
:
Исключение, которое вызывается, когда значение аргумента выходит за допустимый диапазон значений, определяемый вызываемым методом.
Ответ 4
Бросок пустой ссылки на пустую строку может привести к путанице - значение по умолчанию для строки равно нулю и будет указывать на неинициализированную строку, тогда как пустая строка может представлять другие проблемы.
Мне нравится идея Jon Skeet, однако мне нравится явно использовать throw, а не иметь отдельную функцию.
Вместо этого вы можете бросить следующий класс:
public class ArgumentNullOrEmptyException : ArgumentNullException
{
#region Properties And Fields
private static string DefaultMessage => $"A value cannot be null or empty{Environment.NewLine}";
#endregion
#region Construction and Destruction
public ArgumentNullOrEmptyException()
: base(DefaultMessage)
{
}
public ArgumentNullOrEmptyException(string paramName)
: base(paramName,
$"{DefaultMessage}" +
$"Parameter name: {paramName}")
{
}
public ArgumentNullOrEmptyException(string message, Exception innerException)
: base($"{DefaultMessage}{message}", innerException)
{
}
public ArgumentNullOrEmptyException(string paramName, string message)
: base(paramName,
$"{DefaultMessage}" +
$"Parameter name: {paramName}{Environment.NewLine}" +
$"{message}")
{
}
#endregion
public static void ThrowOnNullOrEmpty(string paramName, string paramValue)
{
if(string.IsNullOrEmpty(paramValue))
throw new ArgumentNullOrEmptyException(paramName);
}
public static void ThrowOnNullOrEmpty(string paramValue)
{
if (string.IsNullOrEmpty(paramValue))
throw new ArgumentNullOrEmptyException();
}
public static void ThrowOnNullOrEmpty(string paramName, object paramValue)
{
//ThrowOnNullOrEmpty another object that could be 'empty'
throw new NotImplementedException();
}
}
private static void AFunctionWithAstringParameter(string inputString)
{
if(string.IsNullOrEmpty(inputString)) throw new ArgumentNullOrEmptyException(nameof(inputString));
//Or ..
ArgumentNullOrEmptyException.ThrowOnNullOrEmpty(nameof(inputString), inputString);
}
Обратите внимание, что мой производный тип вызывает только базовый класс исключений, а не переопределяет свойство сообщения. Это связано с тем, что в "дополнительной информации" отладчика Visual Studio указано внутреннее сообщение, а не переопределенный тип. Это означает, что это единственный способ красиво отобразить сообщение во время отладки.