Почему C# допускает перегрузки, когда единственным отличием является необязательный параметр? - PullRequest
2 голосов
/ 05 марта 2020

Почему C # / Framework позволяет мне использовать необязательный параметр для создания перегрузки, которую он иначе не разрешает?

public static TOut? NullableConvert<TOut>(object source, Func<object, TOut> converter) where TOut : struct
{
}

public static TOut NullableConvert<TOut>(object source, Func<object, TOut> converter) where TOut : class
{
}

Когда я пытаюсь выполнить вышеуказанные перегрузки, я получаю следующую ошибку, с которой я согласен:

Ошибка CS0111 Тип 'DataHelpers' уже определяет член с именем 'NullableConvert' с тем же типы параметров


Однако, если я добавлю необязательный параметр к одному из методов, как показано ниже, я получу разрешение на использование этих перегрузок (обратите внимание object x = null).

public static TOut? NullableConvert<TOut>(object source, Func<object, TOut> converter) where TOut : struct
{
}

public static TOut NullableConvert<TOut>(object source, Func<object, TOut> converter, object x = null) where TOut : class
{
}

Когда я запускаю после времени выполнения, исправляются правильные перегрузки без необязательного параметра

long? x = DataHelpers.NullableConvert(DBNull.Value, Convert.ToInt64);
string y = DataHelpers.NullableConvert(DBNull.Value, Convert.ToString);

Как компилятор / среда выполнения могут разрешать перегрузку без необязательный параметр?

Почему я получил ошибку в первую очередь, если методы могут быть разрешены?

Ответы [ 2 ]

5 голосов
/ 05 марта 2020

Перегрузка метода не может отличаться только по типу возвращаемого значения (так же как и общее определение c, только для полноты).

С другой стороны, все вызовы метода с необязательным аргументом просто компилируются в вызов со значением по умолчанию на вызывающем сайте. Так что в вашем случае компилятор превратит это

NullableConvert(DB.Value, Convert.ToString)

в это:

NullableConvert(DB.Value, Convert.ToInt64, null)

при изменении метода

public static TOut NullableConvert<TOut>(object source, Func<object, TOut> converter, object x = null) where TOut : class
{
}

в это:

public static TOut NullableConvert<TOut>(object source, Func<object, TOut> converter, object x) where TOut : class
{
}

Однако нет причины также заменять метод на struct, поскольку для этого метода не определен необязательный параметр. Таким образом, в IL существуют следующие два метода:

public static TOut NullableConvert<TOut>(object source, Func<object, TOut> converter, object x) where TOut : class
{
}
public static TOut? NullableConvert<TOut>(object source, Func<object, TOut> converter) where TOut : struct
{
}

Вызов NullableConvert(DB.Value, Convert.ToString) не будет скомпилирован с вышеупомянутой перегрузкой, поскольку уже существует идеальное соответствие для TOut: struct.

Таким образом, перед тем, как компилятор попытается разрешить любую перегрузку, он заменит любой метод, имеющий необязательные параметры.

1 голос
/ 05 марта 2020

Возвращаемое значение не является частью сигнатуры метода. как уже ответили здесь

а также в документах Microsoft

...