Можно придерживаться такого алгоритма. Выбрасывать exception если:
- В ходе выполнения метода возникла ошибка, поэтому нечего возвращать.
- В ходе выполнения не возникло ошибок, но, по некоторым причинам (например, объект не найден в базе) методу нечего возвращать, а вызывающий код ожидает обязательно получить объект.
Возвращать null если:
- Вызывающий код допускает возвращения null вместо объекта и корректно обрабатывает такой сценарий.
Рассмотрим это все на примере. Допустим, есть метод
User FindUserByName(string name) {},
который осуществляет поиск объекта User в базе данных. Если во время вызова произошла ошибка доступа к данным, то правильнее выкинуть исключение. Если работа с базой прошла корректно, но User с таким именем не найден, то логично вернуть null. Однако, если вызывающий код не допускает работы с null вместо User, то правильнее выкинуть exception.
Вариант №2 Вернуть пустой объект (0, String.Empty, пустой список и т.д.) кажется мало применимым на практике из-за его неинформативности.
Допустим есть метод
string GetUserName(long userId);
Если такой метод вернет string.Empty, то вызывающий код никак не сможет интерпретировать такой результат. Ведь непонятно, произошла ли ошибка доступа к данным или не найден такой пользователь, или пользователь найден, но его имя не задано.
В любом случае, главное — придерживаться стандарта именования методов и поведения в исключительных ситуациях, чтобы все методы вели себя единообразно. Можно, например, называть методы, возвращающие null GetSomeObject()
, а методы, выкидывающие исключения — GetRequiredObject()
и тп.