Использование `NullReferenceException`
Да, я знаю что NullReferenceException — это системная ошибка (наследование от SystemException + применение), но что мне выбрасывать вот в таком коде:
public interface IMyInterface
{
void Import(IModuleSource module);
}
public static class MyExtensions
{
public static void ImportKernel(this IMyInterface @this)
{
@this.Import(new KernelSource(KernelVersion.Latest)); // импортируем ядро
}
}
ПРИМЕЧАНИЕ. Псевдо-код. Фокус должен быть не на методах Import и ImportKernel, а на "прологе" метода ImportKernel.
Тут есть 1 проблема — параметр @this в методе ImportKernel может быть null. Следовательно, этот вход нужно обработать. И тут возникает 2 способа решения:
if (@this is null) throw new ArgumentNullException(nameof(@this));
if (@this is null) throw new NullReferenceException();
Кажется, что 2-й способ неконкурентоспособен, но метод ImportKernel можно вызвать также по разному:
IMyInterface obj = null!;
// исключение `ArgumentNullException` не уместно, т.к. мы не передаём аргумент `this`
// исключение `NullReferenceException` выглядит естественно
obj.ImportKernel();
// исключение `ArgumentNullException` выглядит естественно
// исключение `NullReferenceException` выглядит не уместно, т.к. класс `MyExtensions` не может быть `null` (да он, собственно, и не объект)
MyExtensions.ImportKernel(null!);
И не понятно, что делать?
Конечно, можно создать своё исключение — ObjectNullException, но оно не входит в стандартную библиотеку, значит у каждого будет по такому исключению, что не хорошо.
Собственно, вопрос: какое исключение лучше выбрасывать в данной ситуации (или не выбрасывать ничего на крайняк)?
Ответы (2 шт):
Вариант собственно очевидный для меня. Для кого другой пишите свой ответ.
Вариант. if (@this is null) throw new NullReferenceException(); Не имеет смысла поскольку следующая команда сделает это за вас.
Писать своё исключение это хорошая практика. (не утверждаю о правильности, правильно и хорошо не инвариант. Всё индивидуально).
Я бы сделал лучше так
public static class MyExtensions
{
public static bool IsImportKernelSuccess(this IMyInterface @this)
{
if (@this is null)
return false;
@this.Import(new KernelSource(KernelVersion.Latest));
return true;
}
}
Или можно еще попытаться избежать на входе в метод null с помощью паттерна NullObject.