Перегружает ли единственный способ иметь аргументы функции по умолчанию в С#?

Верно ли, что единственный способ обработки аргументов функции по умолчанию - перегрузка функций?

Например, в PHP я могу это сделать:

function foo($x, $y=0)
{
}

Будет ли лучший способ справиться с этим в С#?

void foo(int x)
{
  foo(x, 0);
}

void foo(int x, int y)
{
}

Пример снят здесь

Изменить

Сделал пример С# в фактическом С# (спасибо Блэру Конраду)

Ответ 1

Да, это было бы лучше , если бы вы не указали $ на имена параметров, как указывали другие. Для тех, кто интересуется обоснованием отсутствия значений параметров по умолчанию, см. Объяснение @Giovanni Galbo.

Ответ 2

Просто чтобы удовлетворить любопытство:

От Почему С# не поддерживает параметры по умолчанию?:

В таких языках, как С++, значение по умолчанию может быть включено как часть объявления метода:

void Process (Employee employee, bool bonus = false)

Этот метод можно вызвать либо с помощью

a.Process(employee, true);

или

a.Process(сотрудник);

во втором случае бонус параметра установлен в значение false.

С# не имеет этой функции.

Одна из причин, почему у нас нет этой функции, связана с конкретной реализацией функции. В мире С++, когда пользователь пишет:

a.Process(сотрудник);

компилятор генерирует

a.process(employee, false);

Другими словами, компилятор принимает значение по умолчанию, указанное в прототипе метода, и помещает его в вызов метода - он точно так же, как если бы пользователь написал "false" в качестве второго параметра. Невозможно изменить это значение по умолчанию, не заставляя пользователя класса перекомпилировать, что является неудачным.

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

Было бы возможно, чтобы компилятор взял что-то вроде определения С++ и произвел перегрузки, но есть несколько проблем с этим подходом.

Первая заключается в том, что корреляция между кодом, который пользователь пишет, и кодом, который генерирует компилятор, менее очевидна. Обычно мы стараемся ограничить магию, когда это возможно, так как это затрудняет программистам. Вторая проблема связана с такими вещами, как комментарии XML doc и intellisense. У компилятора должны быть специальные правила для того, как он генерирует комментарии к документам для перегруженных методов, а intellisense должен иметь smarts для свертывания перегруженных методов в один метод.

Написание перегрузок - это немного менее удобно, но мы считаем это приемлемым решением.

Ответ 3

Относительно отрывок из С# faq:

Большинство проблем, перечисленных там, были решены для VB.Net(в частности, проблем с intellisense и xml-комментариями), что означает, что они действительно красные сельди - есть код, доступный команде С#, которая решит проблему.

Другая причина связана с принуждением пользователя к повторной компиляции класса, но это тоже красная селедка. Если вы измените значение по умолчанию в своем классе инфраструктуры и пользователь не должен перекомпилировать, вы рискуете, что пользователь не будет знать, что значение по умолчанию изменилось. Теперь у вас есть потенциальная ошибка в коде, который не отображается до выполнения. Другими словами, альтернатива перегрузки функции, по крайней мере, такая же плохая. Конечно, это также предполагает конкретную реализацию функции, но это реализация, предложенная в faq.

Поэтому вы должны взвесить оставшуюся причину ( "попытаться ограничить магию" ) и факт (который они признают), что запись перегрузок "немного менее удобна". Лично я говорю о включении функции, и пусть программист решил, использовать ее или нет.

Ответ 4

Аргументы по умолчанию являются частью С++, но по умолчанию аргументы по умолчанию С# 3.5 по-прежнему не поддерживаются - вам придется перегружать. Они доступны в версии VB.Net с версии 1.0.

Ответ 5

Да.

Или каррирование.

Или абстрагироваться в класс и использовать значения по умолчанию.

Ответ 6

Нет, AFAIK С# не поддерживает переопределение, и да, это рекомендуемый способ достижения того же эффекта.

Ответ 7

Это не делает работу?

void foo(int x):this(x, 0){}

void foo(int x, int y){
 // code here
}