TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #2253 2.64K
День 1864. #ЗаметкиНаПолях
Необязательные Параметры Могут Быть в Середине

В .NET необязательные параметры не всегда должны быть последними параметрами в сигнатуре метода. Хотя C# не позволяет объявлять необязательные параметры в середине, это можно сделать в IL или других языках, таких как VB.NET или F#. Кроме того, компилятор может создавать методы с необязательными параметрами в середине списка параметров.

Почему это имеет значение? Если вы пишете генератор исходного кода, который генерирует новые методы с теми же параметрами, что и другой метод, вам может потребоваться сгенерировать методы с необязательными параметрами в середине списка параметров. Хотя это довольно редкий случай, это допустимо в .NET и может быть полезно в некоторых сценариях.

Чтобы лучше понять суть вопроса, начнём с простого примера. Следующий код недопустим в C#:
// CS1737 Optional parameters must appear after all required parameters
void Sample(int a = 1, int b)
{
}

При компиляции метода с необязательными параметрами компилятор заменяет синтаксис C# двумя атрибутами: [Optional] и [DefaultParameterValue]. Атрибут [Optional] используется для пометки параметра как необязательного, а атрибут [DefaultParameterValue] используется для установки значения по умолчанию. Следующий код допустим в C#:
// Вывод: 42
Sample(b: 2);

// Объявляем "a" как необязательный
// со значением 40 по умолчанию
void Sample(
[Optional, DefaultParameterValue(40)]
int a,
int b)
{
Console.WriteLine(a + b);
}

Обратите внимание, что компилятор C# более строг, чем в других языках, в отношении допустимых значений в [DefaultParameterValue]. Он гарантирует, что тип значения совпадает с типом параметра, но может не допускать некоторых допустимых преобразований. Например, следующий код будет допустим в VB.NET или F#, но не в C#:
// CS1908 The type of the argument to the DefaultParameterValue attribute must match the parameter type
void Sample(
[Optional, DefaultParameterValue(default)]
CancellationToken cancellationToken)
{
}

Тот же метод в F# допустим:
type Class1 =
static member Sample(
[<Optional; DefaultParameterValue(CancellationToken())>]
ct: CancellationToken) = ()


Кстати: даже компилятор C# может сгенерировать метод с необязательными параметрами в середине списка параметров. При создании индексатора с необязательными параметрами компилятор генерирует метод с необязательным параметром в середине:
// Создаёт метод (set_Item) с необязательным параметром в середине
// int set_Item(int a, int b = 2, int value)
public int this[int a, int b = 2]
{
set { }
}


Источник: https://www.meziantou.net/optional-parameters.htm
  • 👍 11
  • 👎 2
More from @netdeveloperdiary
  1. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
  2. Oct 7, 2026День 2807. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Окончание Нач…
  3. Oct 6, 2026🦈 Открытое собеседование на Middle C# | 6 октября, 19:00 МСК Приглашаем на открытое собес…
  4. Oct 6, 2026День 2806. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Начало Больши…
  5. Oct 5, 2026День 2805. #ЧтоНовенького #NET11 Аргументы в Выражениях Коллекций в C#15 В C#15 реализован…
  6. Oct 4, 2026День 2804. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →