Ответ 1
Вы можете создать свой собственный тип исключения для соответствующей логики:
public class InitializationException : Exception
{
}
а затем:
throw new InitializationException {Message = "Collection is empty"};
Предположим, что простой пример, когда метод извлекает коллекцию (например, список, содержащий некоторые строки конфигурации), и пытается каким-то образом изучить его:
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
бросать
автоматически (который не обрабатывает ситуацию с пустым списком),
введите настраиваемый тип исключения (возможно, это не очень хорошая идея, поскольку я не ожидаю, что вызывающий объект попытается что-либо сделать с исключением, то есть он не будет искать специальный тип исключения для обработки),
Вы можете создать свой собственный тип исключения для соответствующей логики:
public class InitializationException : Exception
{
}
а затем:
throw new InitializationException {Message = "Collection is empty"};
Я не уверен, что есть одно встроенное исключение, которое вы можете элегантно использовать в этом случае... a NullReferenceException
не подходит, поскольку пустой список не является нулевой ссылкой
Я бы посоветовал обратиться к предлагаемому решению Dmintry, поскольку вызывающий абонент все еще может просто использовать try...catch(Exception)
, не заботясь о том, чтобы исключение действительно было SuperDooperListNullOrEmptyFunTimeException
Так как это либо неустранимая ошибка с точки зрения вызывающей стороны (т.е. они не имеют контроля над выбранным хостом Xml и не контролируют, что загружается XML), то исключение будет либо сбрасываться к журналу или на экране для потребления человеком, после чего он обсуждает - поскольку фактическое сообщение более важно, чем тип.
С другой стороны, если он восстанавливается (вызывающий может повторить попытку метода, убедившись, что xml для загрузки теперь содержит правильно отформатированный xml, или вызывающий может уведомить пользователя и попросить их пойти и исправить XML и "хотите ли вы сейчас повторить попытку?" ), Вам нужно дать им типизированное исключение, чтобы они знали, что он безопасен для повторения, в отличие от простого старого Исключения, которое может означать, что что-то еще ужасно ошибочно, и повторная попытка будет только ухудшить ситуацию...
Это не так много проблем с программированием, как проблема дизайна, причина, по которой объект списка .NET не генерирует исключения, когда они пусты, потому что существует много случаев, когда пустой список является ожидаемой и приемлемой ситуацией.
Если в контексте список, с которым вы работаете, никогда не должен быть пустым, тогда выведите исключение (пользовательское)
Если, однако, возможно и логично, что список может быть пустым, зачем прерывать все это, он исключается не исключительным, так что нужно исключение? Цикл foreach
и пустой список не генерируют исключение, цикл просто не будет зацикливаться.
Что касается нулевой возможности (довольно редко для SelectNodes
, если хорошо понимать), то такая же проблема в некоторых библиотеках или функциях, возвращающих null
, является нормальным поведением, а не исключением.
Enumerable.First создает исключение System.InvalidOperationException, если коллекция пуста. Вы могли бы, я думаю.
throw new InvalidOperationException("Sequence contains no elements");
https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.first?view=netframework-4.8