Одним из предостережений необязательных параметров является управление версиями, когда рефакторинг имеет непредвиденные последствия. Пример:
Исходный код
public string HandleError(string message, bool silent=true, bool isCritical=true)
{
...
}
Предположим, что это один из многих абонентов вышеуказанного метода:
HandleError("Disk is full", false);
Здесь событие не является бесшумным и рассматривается как критическое.
Теперь, скажем, после рефакторинга мы обнаружим, что все ошибки все равно подсказывают пользователю, поэтому нам больше не нужен флаг без вывода сообщений. Итак, мы удалим его.
После рефакторинга
Первый вызов все еще компилируется, и, скажем, он пропускает рефакторинг без изменений:
public string HandleError(string message, /*bool silent=true,*/ bool isCritical=true)
{
...
}
...
// Some other distant code file:
HandleError("Disk is full", false);
Теперь false
будет иметь непреднамеренный эффект, событие больше не будет рассматриваться как критическое.
Это может привести к незначительному дефекту, поскольку не будет никаких ошибок компиляции или времени выполнения (в отличие от некоторых других предостережений дополнительных опций, таких как this или this ).
Обратите внимание, что есть много форм этой же проблемы. Еще одна форма обозначена здесь .
Обратите внимание, что строгое использование именованных параметров при вызове метода позволит избежать этой проблемы, например: HandleError("Disk is full", silent:false)
. Однако может быть нецелесообразно предполагать, что все другие разработчики (или пользователи общедоступного API) будут делать это.
По этим причинам я бы избегал использования необязательных параметров в общедоступном API (или даже в общедоступном методе, если его можно было бы широко использовать), если нет других убедительных соображений.