Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю. Страница 86

EnterLogData("Oh no! I can't find the payroll data", "CFO");

Console.ReadLine();

Из-за того, что в первом вызове

EnterLogData()
не был указан второй аргумент
string
, будет использоваться его стандартное значение —
"Programmer"
. Во втором вызове
EnterLogData()
для второго аргумента передано значение
"CFO"
.

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

EnterLogData()
, добавив к нему дополнительный необязательный параметр:

// Ошибка! Стандартное значение для необязательного

// аргумента должно быть известно на этапе компиляции!

static void EnterLogData(string message,

    string owner = "Programmer", DateTime timeStamp =
DateTime.Now)

{

  Console.Beep();

  Console.WriteLine("Error: {0}", message);  // Сведения об ошибке

  Console.WriteLine("Owner of Error: {0}", owner); // Владелец ошибки

  Console.WriteLine("Time of Error: {0}", timeStamp);

                                             // Время возникновения ошибки

}

Такой код не скомпилируется, поскольку значение свойства

Now
класса
DateTime
вычисляется во время выполнения, а не на этапе компиляции.

На заметку! Во избежание неоднозначности необязательные параметры должны всегда помещаться в конец сигнатуры метода. Если необязательные параметры обнаруживаются перед обязательными, тогда компилятор сообщит об ошибке.

Использование именованных параметров (обновление в версии 7.2)

Еще одним полезным языковым средством C# является поддержка именованных аргументов. Именованные аргументы позволяют вызывать метод с указанием значений параметров в любом желаемом порядке. Таким образом, вместо передачи параметров исключительно по позициям (как делается в большинстве случаев) можно указывать имя каждого аргумента, двоеточие и конкретное значение. Чтобы продемонстрировать использование именованных аргументов, добавьте в класс

Program
следующий метод:

static void DisplayFancyMessage(ConsoleColor textColor,

  ConsoleColor backgroundColor, string message)

{

  //Сохранить старые цвета для их восстановления после вывода сообщения.

  ConsoleColor oldTextColor = Console.ForegroundColor;

  ConsoleColor oldbackgroundColor = Console.BackgroundColor;

  // Установить новые цвета и вывести сообщение.

  Console.ForegroundColor = textColor;

  Console.BackgroundColor = backgroundColor;

  Console.WriteLine(message);

  // Восстановить предыдущие цвета.

  Console.ForegroundColor = oldTextColor;

  Console.BackgroundColor = oldbackgroundColor;

}

Теперь, когда метод

DisplayFancyMessage()
написан, можно было бы ожидать, что при его вызове будут передаваться две переменные типа
ConsoleColor
, за которыми следует переменная типа
string
. Однако с помощью именованных аргументов метод
DisplayFancyMessage()
допустимо вызывать и так, как показано ниже:

Console.WriteLine("***** Fun with Methods *****");

DisplayFancyMessage(message: "Wow! Very Fancy indeed!",

  textColor: ConsoleColor.DarkRed,

  backgroundColor: ConsoleColor.White);

DisplayFancyMessage(backgroundColor: ConsoleColor.Green,

  message: "Testing...",

  textColor: ConsoleColor.DarkBlue);

Console.ReadLine();

В версии C# 7.2 правила применения именованных аргументов слегка изменились. До выхода C# 7.2 при вызове метода позиционные параметры должны были располагаться перед любыми именованными параметрами. В C# 7.2 и последующих версиях именованные и неименованные параметры можно смешивать, если параметры находятся в корректных позициях.

На заметку! Хотя в C# 7.2 и последующих версиях именованные и позиционные аргументы можно смешивать, поступать так — не особо удачная идея. Возможность не значит обязательность!

Ниже приведен пример:

<b>// Все нормально, т.к. позиционные аргументы находятся перед именованными.</b>

DisplayFancyMessage(ConsoleColor.Blue,

                    message: &quot;Testing...&quot;,

                    backgroundColor: ConsoleColor.White);

<b>// Все нормально, т.к. все аргументы располагаются в корректном порядке.</b>

DisplayFancyMessage(textColor: ConsoleColor.White,

                    backgroundColor:ConsoleColor.Blue,

                    &quot;Testing...&quot;);

<b>// ОШИБКА в вызове, поскольку позиционные аргументы следуют после именованных.</b>

DisplayFancyMessage(message: &quot;Testing...&quot;,

                    backgroundColor: ConsoleColor.White,