Объявление, константа и шаблоны var

Tip

Эта статья является частью раздела "Основы" для разработчиков , которые уже знают хотя бы один язык программирования и учат C#. Начните с обзора сопоставления шаблонов , если вы раньше не использовали шаблоны C#. Полные языковые правила см. в справочнике по шаблонам.

Шаблон применяется к входным выражениям. C# вычисляет выражение, а затем тестирует шаблон или записывает полученное значение. Объявление, константа и var шаблоны отвечают на три практических вопроса:

  • Шаблон объявления: Создает ли выражение ненулевое значение совместимого типа времени выполнения? Если да, объявите переменную для этого значения.
  • Шаблон констант: Создает ли выражение одно определенное константное значение?
  • var шаблон: какое значение производит выражение? Захватите его без предварительной проверки его типа или значения.

Проверить и захватить тип с помощью шаблона объявления

Шаблон объявления состоит из типа и обозначения. Тип указывает тип времени выполнения для тестирования. Обозначение объявляет переменную, которая получает соответствующее значение.

В следующем примере получается выражение object, поэтому выражение может создавать различные типы. Шаблон объявления позволяет соответствующей ветви использовать десятичную сумму без отдельного теста типа и приведения:

static void PrintPrice(object value)
{
    if (value is decimal amount)
    {
        Console.WriteLine($"Price: {amount:C}");
    }
}

В value is decimal amount:

  • value — это входное выражение. C# сначала вычисляет его.
  • decimal — тестируемый тип. Шаблон совпадает, если вычисляемое значение не равно null, а его тип времени выполнения совместим с decimal.
  • amount — это обозначение. Когда шаблон совпадает, объявляется amount, и ему присваивается значение типа decimal.

Компилятор отслеживает, получает ли локальная переменная значение, прежде чем код считывает его. Это отслеживание называется определенным присваиванием. Внутри блока if компилятор знает, что amount было присвоено значение, поскольку блок выполняется только в случае совпадения с шаблоном. Компилятор создает ошибку, если код пытается получить доступ amount за пределами if блока. Если value не является значением decimal, переменной amount не присваивается значение.

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

Вы также можете использовать шаблоны объявлений, если одно выражение может создать несколько полезных типов:

static string FormatSensorValue(object reading) =>
    reading switch
    {
        int count => $"Count: {count}",
        double temperature => $"Temperature: {temperature:F1}°C",
        string message => $"Message: {message}",
        _ => "Unsupported reading"
    };

Каждая ветвь объявляет переменную совпавшего типа, поскольку результату требуется логика форматирования для этого типа. Шаблон объявления совпадает только в том случае, если вычисляемое значение не равно NULL и уже имеет тип времени выполнения, совместимый с тестируемым типом через преобразования, разрешенные для шаблонов. null не имеет типа времени выполнения для сопоставления шаблона. Шаблон также не выполняет определяемые пользователем операторы преобразования: это тест типа и запись, а не запрос на преобразование значения в другой тип. Полные правила совместимости см. в разделе "Объявления" и "шаблоны типов".

Сопоставление определенного значения с константным шаблоном

Константный шаблон проверяет, создает ли выражение определенную константу, например число, строку, логический элемент, член перечисления, объявленное const значение илиnull.

Шаблоны констант соответствуют выражению коммутатора, когда несколько известных значений создают другой результат:

static string GetCommandMessage(Command command) =>
    command switch
    {
        Command.Start => "Starting",
        Command.Stop => "Stopping",
        Command.Pause => "Pausing",
        _ => "Unknown command"
    };

Command — это перечисление, тип, определяющий набор именованных констант. Command.Start, Command.Stopи Command.Pause являются его элементами перечисления, поэтому каждая рука коммутатора использует постоянный шаблон для проверки одного именованного значения команды.

Выберите эту форму, когда команда может иметь несколько дискретных значений. Ветви switch сохраняют значения и соответствующие им результаты вместе. Для одной простой проверки на равенство инструкцию if (command == Command.Start), например if, обычно легче читать.

Сопоставление константных шаблонов использует встроенные правила равенства языка, а не определяемый == пользователем оператор. Подробные сведения о правилах равенства и преобразования см. в справочнике по шаблонам констант.

Шаблон null константы полезен для надежной проверки null:

static bool HasText(string? text) => text is not null;

Выберите is null или is not null при проверке состояния NULL. Эти шаблоны не вызывают определяемый пользователем оператор равенства, даже если для типа выражения перегружен оператор ==.

Захватить результат для guard с шаблоном var

Шаблонvar соответствует каждому результату, включая nullи объявляет переменную, тип которой является типом входного выражения во время компиляции. Он может записать вычисленное значение, а другой шаблон уже соответствует объекту:

static string GetDeliveryMessage(object delivery) =>
    delivery switch
    {
        ExpressDelivery express
            when EstimateDays(express) is var days && days <= 2
                => $"Arrives in {days} day{(days == 1 ? "" : "s")}",
        ExpressDelivery => "Express delivery for your location takes more than two days",
        _ => "Standard delivery"
    };

static int EstimateDays(ExpressDelivery delivery) =>
    delivery.MilesAway <= 500 ? 1 :
    delivery.MilesAway <= 1_000 ? 2 : 3;

record ExpressDelivery(int MilesAway);

Шаблон ExpressDelivery express объявления сначала фиксирует объект доставки как express. Вызов EstimateDays(express) метода — это входное выражение для var шаблона. C# вычисляет этот вызов метода и var days записывает итоговую оценку, как days без тестирования типа или значения. Срок оценки может составлять один-два дня, если проверка проходит успешно. Для вывода фактического количества дней результату ветви требуется захваченное значение.

Обычную локальную переменную нельзя объявить между шаблоном ветви switch и её условием when. Повторный вызов EstimateDays(express) в результирующем выражении приведёт к повторному вычислению. Выберите эту var форму шаблона, когда код уже соответствует, и охранник и результат требуют вычисленного промежуточного значения.

Если захваченное значение не требуется, используйте шаблон _отбрасывания вместо объявления переменной.

См. также