Какой тип исключения следует выбрасывать, если список/коллекция пуст или нулевым и не может быть повторен (не параметр)?

Предположим, что простой пример, когда метод извлекает коллекцию (например, список, содержащий некоторые строки конфигурации), и пытается каким-то образом изучить его:

void Init()
{
    XmlDocument config = new XmlDocument();
    config.Load(someXml);
    var list = config.SelectNodes("/root/strings/key"); // Normally, list should not be null or empty

    if (list == null || list.Count == 0)
        throw new SomeExceptionType(message);   // What kind of exception to throw?

    // Iterate list and process/examine its elements
    foreach (var e in list) ...
}

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

  • ничего не бросать вручную и NullReferenceException бросать автоматически (который не обрабатывает ситуацию с пустым списком),

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

  • сделать что-то еще?

Ответ 1

Вы можете создать свой собственный тип исключения для соответствующей логики:

public class InitializationException : Exception
{
}

а затем:

throw new InitializationException {Message = "Collection is empty"};

Ответ 2

Я не уверен, что есть одно встроенное исключение, которое вы можете элегантно использовать в этом случае... a NullReferenceException не подходит, поскольку пустой список не является нулевой ссылкой

Я бы посоветовал обратиться к предлагаемому решению Dmintry, поскольку вызывающий абонент все еще может просто использовать try...catch(Exception), не заботясь о том, чтобы исключение действительно было SuperDooperListNullOrEmptyFunTimeException

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

С другой стороны, если он восстанавливается (вызывающий может повторить попытку метода, убедившись, что xml для загрузки теперь содержит правильно отформатированный xml, или вызывающий может уведомить пользователя и попросить их пойти и исправить XML и "хотите ли вы сейчас повторить попытку?" ), Вам нужно дать им типизированное исключение, чтобы они знали, что он безопасен для повторения, в отличие от простого старого Исключения, которое может означать, что что-то еще ужасно ошибочно, и повторная попытка будет только ухудшить ситуацию...

Ответ 3

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

Если в контексте список, с которым вы работаете, никогда не должен быть пустым, тогда выведите исключение (пользовательское)

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

Что касается нулевой возможности (довольно редко для SelectNodes, если хорошо понимать), то такая же проблема в некоторых библиотеках или функциях, возвращающих null, является нормальным поведением, а не исключением.