Шаблоны (справочник по C#)Patterns (C# reference)

Возможность использовать сопоставление шаблонов впервые появилась в C# 7.0.C# introduced pattern matching in C# 7.0. С тех пор в каждой новой основной версии C# возможности сопоставления шаблонов расширяются.Since then, each major C# version extends pattern matching capabilities. Сопоставление шаблонов поддерживают следующие выражения и операторы C#:The following C# expressions and statements support pattern matching:

В этих конструкциях можно сравнить входное выражение с любым из следующих шаблонов:In those constructs, you can match an input expression against any of the following patterns:

  • Шаблон объявления: для проверки типа выражения в среде выполнения и, в случае равенства, присвоения объявленной переменной результата этого выражения.Declaration pattern: to check the runtime type of an expression and, if a match succeeds, assign an expression result to a declared variable. Впервые появился в C# 7.0.Introduced in C# 7.0.
  • Шаблон типа: для проверки типа выражения в среде выполнения.Type pattern: to check the runtime type of an expression. Впервые появился в C# 9.0.Introduced in C# 9.0.
  • Шаблон константы: для проверки того, равен ли результат выражения указанной константе.Constant pattern: to test if an expression result equals a specified constant. Впервые появился в C# 7.0.Introduced in C# 7.0.
  • Реляционные шаблоны: для сравнения результата выражения с заданной константой.Relational patterns: to compare an expression result with a specified constant. Впервые появился в C# 9.0.Introduced in C# 9.0.
  • Логические шаблоны: для проверки того, соответствует ли выражение логической комбинации шаблонов.Logical patterns: to test if an expression matches a logical combination of patterns. Впервые появился в C# 9.0.Introduced in C# 9.0.
  • Шаблон свойства: для проверки того, соответствуют ли свойства или поля выражения вложенным шаблонам.Property pattern: to test if an expression's properties or fields match nested patterns. Впервые появился в C# 8.0.Introduced in C# 8.0.
  • Позиционный шаблон: для деконструкции результата выражения и проверки того, соответствуют ли результирующие значения вложенным шаблонам.Positional pattern: to deconstruct an expression result and test if the resulting values match nested patterns. Впервые появился в C# 8.0.Introduced in C# 8.0.
  • Шаблон var: для сравнения любых выражений и присваивания результата сравнения объявленной переменной.var pattern: to match any expression and assign its result to a declared variable. Впервые появился в C# 7.0.Introduced in C# 7.0.
  • Шаблон пустой переменной: для сравнения любых выражений.Discard pattern: to match any expression. Впервые появился в C# 8.0.Introduced in C# 8.0.

Логические шаблоны, шаблоны свойств и позиционные шаблоны являются рекурсивными шаблонами.Logical, property, and positional patterns are recursive patterns. То есть, они могут содержать вложенные шаблоны.That is, they can contain nested patterns.

Пример использования этих шаблонов для создания управляемого данными алгоритма можно посмотреть в разделе Учебник: использование сопоставления шаблонов для создания управляемых типами и управляемых данными алгоритмов.For the example of how to use those patterns to build a data-driven algorithm, see Tutorial: Use pattern matching to build type-driven and data-driven algorithms.

Шаблоны объявления и шаблоны типовDeclaration and type patterns

Шаблоны объявления и шаблоны типов используются для проверки того, совместим ли с указанным типом тип определенного выражения в среде выполнения.You use declaration and type patterns to check if the runtime type of an expression is compatible with a given type. С помощью шаблона объявления можно также объявить новую локальную переменную.With a declaration pattern, you can also declare a new local variable. Если шаблон объявления соответствует выражению, этой переменной присваивается результат преобразованного выражения, как показано в следующем примере:When a declaration pattern matches an expression, that variable is assigned a converted expression result, as the following example shows:

object greeting = "Hello, World!";
if (greeting is string message)
{
    Console.WriteLine(message.ToLower());  // output: hello, world!
}

Начиная с C# 7.0, шаблон объявления с типом T соответствует выражению в том случае, если результат выражения имеет значение, отличное от NULL, и выполняется любое из следующих условий:Beginning with C# 7.0, a declaration pattern with type T matches an expression when an expression result is non-null and any of the following conditions are true:

  • Тип результата выражения в среде выполнения — T.The runtime type of an expression result is T.

  • Тип результата выражения в среде выполнения является производным от типа T или реализует интерфейс T или существует другое неявное преобразования ссылок из него в T.The runtime type of an expression result derives from type T or implements interface T or another implicit reference conversion exists from it to T. В следующем примере показаны два случая, когда данное условие истинно:The following example demonstrates two cases when this condition is true:

    var numbers = new int[] { 10, 20, 30 };
    Console.WriteLine(GetSourceLabel(numbers));  // output: 1
    
    var letters = new List<char> { 'a', 'b', 'c', 'd' };
    Console.WriteLine(GetSourceLabel(letters));  // output: 2
    
    static int GetSourceLabel<T>(IEnumerable<T> source) => source switch
    {
        Array array => 1,
        ICollection<T> collection => 2,
        _ => 3,
    };
    

    В предыдущем примере при первом вызове метода GetSourceLabel первый шаблон соответствует значению аргумента, так как тип этого аргумента (int[]) в среде выполнения является производным от типа Array.In the preceding example, at the first call to the GetSourceLabel method, the first pattern matches an argument value because the argument's runtime type int[] derives from the Array type. При втором вызове метода GetSourceLabel тип аргумента в среде выполнения (List<T>) не является производным от типа Array, но реализует интерфейс ICollection<T>.At the second call to the GetSourceLabel method, the argument's runtime type List<T> doesn't derive from the Array type but implements the ICollection<T> interface.

  • Тип результата выражения в среде выполнения является типом, допускающим значение NULL, и имеющим базовый тип T.The runtime type of an expression result is a nullable value type with the underlying type T.

  • Существует упаковка-преобразование или распаковка-преобразование из типа результата выражения в среде выполнения в тип T.A boxing or unboxing conversion exists from the runtime type of an expression result to type T.

В следующем примере показаны два последних условия:The following example demonstrates the last two conditions:

int? xNullable = 7;
int y = 23;
object yBoxed = y;
if (xNullable is int a && yBoxed is int b)
{
    Console.WriteLine(a + b);  // output: 30
}

Если требуется проверить только тип выражения, можно вместо имени переменной использовать пустую переменную _, как показано в следующем примере:If you want to check only the type of an expression, you can use a discard _ in place of a variable's name, as the following example shows:

public abstract class Vehicle {}
public class Car : Vehicle {}
public class Truck : Vehicle {}

public static class TollCalculator
{
    public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
    {
        Car _ => 2.00m,
        Truck _ => 7.50m,
        null => throw new ArgumentNullException(nameof(vehicle)),
        _ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
    };
}

Начиная с C# 9.0, для этой цели можно использовать шаблон типа, как показано в следующем примере:Beginning with C# 9.0, for that purpose you can use a type pattern, as the following example shows:

public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
{
    Car => 2.00m,
    Truck => 7.50m,
    null => throw new ArgumentNullException(nameof(vehicle)),
    _ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
};

Как и шаблон объявления, шаблон типа соответствует выражению, если результат выражения не равен NULL, а его тип в среде выполнения удовлетворяет любому из указанных выше условий.Like a declaration pattern, a type pattern matches an expression when an expression result is non-null and its runtime type satisfies any of the conditions listed above.

Дополнительные сведения см. в разделах Шаблон объявления и Шаблон типа в примечаниях к предлагаемой функции.For more information, see the Declaration pattern and Type pattern sections of the feature proposal notes.

Шаблон константыConstant pattern

Начиная с C# 7.0, вы можете использовать шаблон константы для проверки того, равен ли результат выражения заданной константе, как показано в следующем примере:Beginning with C# 7.0, you use a constant pattern to test if an expression result equals a specified constant, as the following example shows:

public static decimal GetGroupTicketPrice(int visitorCount) => visitorCount switch
{
    1 => 12.0m,
    2 => 20.0m,
    3 => 27.0m,
    4 => 32.0m,
    0 => 0.0m,
    _ => throw new ArgumentException($"Not supported number of visitors: {visitorCount}", nameof(visitorCount)),
};

В шаблоне константы можно использовать любое константное выражение, например:In a constant pattern, you can use any constant expression, such as:

Используйте шаблон константы для проверки на null, как показано в следующем примере:Use a constant pattern to check for null, as the following example shows:

if (input is null)
{
    return;
}

Компилятор гарантирует, что при вычислении выражения x is null не будет вызван перегруженный пользователем оператор равенства ==.The compiler guarantees that no user-overloaded equality operator == is invoked when expression x is null is evaluated.

Начиная с C# 9.0, вы можете использовать шаблон константы null с отрицанием для проверки неравенства значению NULL, как показано в следующем примере:Beginning with C# 9.0, you can use a negated null constant pattern to check for non-null, as the following example shows:

if (input is not null)
{
    // ...
}

Дополнительные сведения см. в разделе Шаблон константы в примечании к предлагаемой функции.For more information, see the Constant pattern section of the feature proposal note.

Реляционные шаблоныRelational patterns

Начиная с C# 9.0, вы можете использовать реляционный шаблон для сравнения результата выражения с константой, как показано в следующем примере:Beginning with C# 9.0, you use a relational pattern to compare an expression result with a constant, as the following example shows:

Console.WriteLine(Classify(13));  // output: Too high
Console.WriteLine(Classify(double.NaN));  // output: Unknown
Console.WriteLine(Classify(2.4));  // output: Acceptable

static string Classify(double measurement) => measurement switch
{
    < -4.0 => "Too low",
    > 10.0 => "Too high",
    double.NaN => "Unknown",
    _ => "Acceptable",
};

В реляционном шаблоне можно использовать любые операторы отношений — <, >, <=, >=.In a relational pattern, you can use any of the relational operators <, >, <=, or >=. Правая часть реляционного шаблона должна быть константным выражением.The right-hand part of a relational pattern must be a constant expression. Константное выражение может быть целым числом, числом с плавающей точкой, символом или иметь тип enum.The constant expression can be of an integer, floating-point, char, or enum type.

Чтобы проверить, находится ли результат выражения в определенном диапазоне, сопоставьте его с шаблоном конъюнкции (and), как показано в следующем примере:To check if an expression result is in a certain range, match it against a conjunctive and pattern, as the following example shows:

Console.WriteLine(GetCalendarSeason(new DateTime(2021, 3, 14)));  // output: spring
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 7, 19)));  // output: summer
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 2, 17)));  // output: winter

static string GetCalendarSeason(DateTime date) => date.Month switch
{
    >= 3 and < 6 => "spring",
    >= 6 and < 9 => "summer",
    >= 9 and < 12 => "autumn",
    12 or (>= 1 and < 3) => "winter",
    _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
};

Если результат выражения — null или его не удается преобразовать в тип константы с помощью преобразования, допускающего значение NULL, или распаковки-преобразования, то реляционный шаблон не соответствует выражению.If an expression result is null or fails to convert to the type of a constant by a nullable or unboxing conversion, a relational pattern doesn't match an expression.

Дополнительные сведения см. в разделе Реляционные шаблоны в примечании к предлагаемой функции.For more information, see the Relational patterns section of the feature proposal note.

Логические шаблоныLogical patterns

Начиная с C# 9.0, вы можете использовать блоки объединения not, and и or для создания следующих логических шаблонов:Beginning with C# 9.0, you use the not, and, and or pattern combinators to create the following logical patterns:

  • Шаблон отрицания not, который соответствует выражению, если шаблон с отрицанием не соответствует выражению.Negation not pattern that matches an expression when the negated pattern doesn't match the expression. В следующем примере показано, как можно инвертировать шаблон константы null, чтобы проверить, имеет ли выражение значение, отличное от NULL:The following example shows how you can negate a constant null pattern to check if an expression is non-null:

    if (input is not null)
    {
        // ...
    }
    
  • Шаблон конъюнкции and, который соответствует выражению, если оба шаблона соответствуют этому выражению.Conjunctive and pattern that matches an expression when both patterns match the expression. В следующем примере показано, как можно объединить реляционные шаблоны, чтобы проверить, находится ли значение в определенном диапазоне:The following example shows how you can combine relational patterns to check if a value is in a certain range:

    Console.WriteLine(Classify(13));  // output: High
    Console.WriteLine(Classify(-100));  // output: Too low
    Console.WriteLine(Classify(5.7));  // output: Acceptable
    
    static string Classify(double measurement) => measurement switch
    {
        < -40.0 => "Too low",
        >= -40.0 and < 0 => "Low",
        >= 0 and < 10.0 => "Acceptable",
        >= 10.0 and < 20.0 => "High",
        >= 20.0 => "Too high",
        double.NaN => "Unknown",
    };
    
  • Шаблон дизъюнкции or, который соответствует выражению, если любой из шаблонов соответствует данному выражению, как показано в следующем примере:Disjunctive or pattern that matches an expression when either of patterns matches the expression, as the following example shows:

    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 1, 19)));  // output: winter
    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 10, 9)));  // output: autumn
    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 5, 11)));  // output: spring
    
    static string GetCalendarSeason(DateTime date) => date.Month switch
    {
        3 or 4 or 5 => "spring",
        6 or 7 or 8 => "summer",
        9 or 10 or 11 => "autumn",
        12 or 1 or 2 => "winter",
        _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
    };
    

Как показано в предыдущем примере, блоки объединения в шаблоне можно использовать многократно.As the preceding example shows, you can repeatedly use the pattern combinators in a pattern.

Блок объединения шаблонов and имеет более высокий приоритет, чем or.The and pattern combinator has higher precedence than or. Чтобы явно задать приоритет, используйте круглые скобки, как показано в следующем примере:To explicitly specify the precedence, use parentheses, as the following example shows:

static bool IsLetter(char c) => c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z');

Примечание

Порядок проверки шаблонов не определен.The order in which patterns are checked is undefined. Во время выполнения можно сначала проверить правые вложенные шаблоны шаблонов or и and.At run time, the right-hand nested patterns of or and and patterns can be checked first.

Дополнительные сведения см. в разделе Блоки объединения шаблонов в примечании к предлагаемой функции.For more information, see the Pattern combinators section of the feature proposal note.

Шаблон свойстваProperty pattern

Начиная с C# 8.0, вы можете использовать шаблон свойства для сопоставления свойств или полей выражения с вложенными шаблонами, как показано в следующем примере:Beginning with C# 8.0, you use a property pattern to match an expression's properties or fields against nested patterns, as the following example shows:

static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };

Шаблон свойства соответствует выражению, если результат выражения не равен NULL, а каждый вложенный шаблон соответствует соответствующему свойству или полю результата выражения.A property pattern matches an expression when an expression result is non-null and every nested pattern matches the corresponding property or field of the expression result.

Вы также можете добавить в шаблон свойства проверку типа среды выполнения и объявление переменной, как показано в следующем примере:You can also add a runtime type check and a variable declaration to a property pattern, as the following example shows:

Console.WriteLine(TakeFive("Hello, world!"));  // output: Hello
Console.WriteLine(TakeFive("Hi!"));  // output: Hi!
Console.WriteLine(TakeFive(new[] { '1', '2', '3', '4', '5', '6', '7' }));  // output: 12345
Console.WriteLine(TakeFive(new[] { 'a', 'b', 'c' }));  // output: abc

static string TakeFive(object input) => input switch
{
    string { Length: >= 5 } s => s.Substring(0, 5),
    string s => s,

    ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()),
    ICollection<char> symbols => new string(symbols.ToArray()),

    null => throw new ArgumentNullException(nameof(input)),
    _ => throw new ArgumentException("Not supported input type."),
};

Шаблон свойства является рекурсивным шаблоном.A property pattern is a recursive pattern. Это значит, что любой шаблон можно использовать как вложенный шаблон.That is, you can use any pattern as a nested pattern. Используйте шаблон свойства для сопоставления элементов данных с вложенными шаблонами, как показано в следующем примере:Use a property pattern to match parts of data against nested patterns, as the following example shows:

public record Point(int X, int Y);
public record Segment(Point Start, Point End);

static bool IsAnyEndAtOrigin(Segment segment) =>
    segment is { Start: { X: 0, Y: 0 } } or { End: { X: 0, Y: 0 } };

В предыдущем примере используются две возможности, доступные в C# 9.0 и более поздних версиях языка: блок объединения шаблонов orи типы записей.The preceding example uses two features available in C# 9.0 and later: or pattern combinator and record types.

Дополнительные сведения см. в разделе Шаблон свойства в примечании к предлагаемой функции.For more information, see the Property pattern section of the feature proposal note.

Позиционный шаблонPositional pattern

Начиная с C# 8.0, вы можете использовать позиционный шаблон для деконструкции результата выражения и сравнения результирующих значений с соответствующими вложенными шаблонами, как показано в следующем примере:Beginning with C# 8.0, you use a positional pattern to deconstruct an expression result and match the resulting values against the corresponding nested patterns, as the following example shows:

public readonly struct Point
{
    public int X { get; }
    public int Y { get; }

    public Point(int x, int y) => (X, Y) = (x, y);

    public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}

static string Classify(Point point) => point switch
{
    (0, 0) => "Origin",
    (1, 0) => "positive X basis end",
    (0, 1) => "positive Y basis end",
    _ => "Just a point",
};

В предыдущем примере тип выражения содержит метод Deconstruct, используемый для деконструкции результата выражения.At the preceding example, the type of an expression contains the Deconstruct method, which is used to deconstruct an expression result. Можно также сопоставлять выражения кортежных типов с позиционными шаблонами.You can also match expressions of tuple types against positional patterns. Таким образом можно сопоставить несколько входных значений с различными шаблонами, как показано в следующем примере:In that way, you can match multiple inputs against various patterns, as the following example shows:

static decimal GetGroupTicketPriceDiscount(int groupSize, DateTime visitDate)
    => (groupSize, visitDate.DayOfWeek) switch
    {
        (<= 0, _) => throw new ArgumentException("Group size must be positive."),
        (_, DayOfWeek.Saturday or DayOfWeek.Sunday) => 0.0m,
        (>= 5 and < 10, DayOfWeek.Monday) => 20.0m,
        (>= 10, DayOfWeek.Monday) => 30.0m,
        (>= 5 and < 10, _) => 12.0m,
        (>= 10, _) => 15.0m,
        _ => 0.0m,
    };

В предыдущем примере используются реляционные и логические шаблоны, доступные в C# 9.0 и более поздних версиях языка.The preceding example uses relational and logical patterns, which are available in C# 9.0 and later.

В позиционном шаблоне можно использовать имена элементов кортежа и параметры метода Deconstruct, как показано в следующем примере:You can use the names of tuple elements and Deconstruct parameters in a positional pattern, as the following example shows:

var numbers = new List<int> { 1, 2, 3 };
if (SumAndCount(numbers) is (Sum: var sum, Count: > 0))
{
    Console.WriteLine($"Sum of [{string.Join(" ", numbers)}] is {sum}");  // output: Sum of [1 2 3] is 6
}

static (double Sum, int Count) SumAndCount(IEnumerable<int> numbers)
{
    int sum = 0;
    int count = 0;
    foreach (int number in numbers)
    {
        sum += number;
        count++;
    }
    return (sum, count);
}

Можно также расширить позиционный шаблон одним из следующих способов:You can also extend a positional pattern in any of the following ways:

  • Добавьте проверку типа среды выполнения и объявление переменной, как показано в следующем примере:Add a runtime type check and a variable declaration, as the following example shows:

    public record Point2D(int X, int Y);
    public record Point3D(int X, int Y, int Z);
    
    static string PrintIfAllCoordinatesArePositive(object point) => point switch
    {
        Point2D (> 0, > 0) p => p.ToString(),
        Point3D (> 0, > 0, > 0) p => p.ToString(),
        _ => string.Empty,
    };
    

    В предыдущем примере используются позиционные записи, которые неявно обеспечивают выполнение метода Deconstruct.The preceding example uses positional records that implicitly provide the Deconstruct method.

  • Используйте шаблон свойства в позиционном шаблоне, как показано в следующем примере:Use a property pattern within a positional pattern, as the following example shows:

    public record WeightedPoint(int X, int Y)
    {
        public double Weight { get; set; }
    }
    
    static bool IsInDomain(WeightedPoint point) => point is (>= 0, >= 0) { Weight: >= 0.0 };
    
  • Можно объединить два предыдущих варианта, как показано в следующем примере:Combine two preceding usages, as the following example shows:

    if (input is WeightedPoint (> 0, > 0) { Weight: > 0.0 } p)
    {
        // ..
    }
    

Позиционный шаблон является рекурсивным шаблоном.A positional pattern is a recursive pattern. Это значит, что любой шаблон можно использовать как вложенный шаблон.That is, you can use any pattern as a nested pattern.

Дополнительные сведения см. в разделе Позиционный шаблон в примечании к предлагаемой функции.For more information, see the Positional pattern section of the feature proposal note.

Шаблон varvar pattern

Начиная с C# 7.0, шаблон var можно использовать для сопоставления любого выражения, включая null, и присвоения результата сопоставления новой локальной переменной, как показано в следующем примере:Beginning with C# 7.0, you use a var pattern to match any expression, including null, and assign its result to a new local variable, as the following example shows:

static bool IsAcceptable(int id, int absLimit) =>
    SimulateDataFetch(id) is var results 
    && results.Min() >= -absLimit 
    && results.Max() <= absLimit;

static int[] SimulateDataFetch(int id)
{
    var rand = new Random();
    return Enumerable
               .Range(start: 0, count: 5)
               .Select(s => rand.Next(minValue: -10, maxValue: 11))
               .ToArray();
}

Шаблон var полезно использовать, если в логическом выражении вам требуется временная переменная для хранения результатов промежуточных вычислений.A var pattern is useful when you need a temporary variable within a Boolean expression to hold the result of intermediate calculations. Шаблон var также можно использовать, если требуется реализовать дополнительные проверки в условиях регистра when выражения или оператора switch, как показано в следующем примере:You can also use a var pattern when you need to perform additional checks in when case guards of a switch expression or statement, as the following example shows:

public record Point(int X, int Y);

static Point Transform(Point point) => point switch
{
    var (x, y) when x < y => new Point(-x, y),
    var (x, y) when x > y => new Point(x, -y),
    var (x, y) => new Point(x, y),
};

static void TestTransform()
{
    Console.WriteLine(Transform(new Point(1, 2)));  // output: Point { X = -1, Y = 2 }
    Console.WriteLine(Transform(new Point(5, 2)));  // output: Point { X = 5, Y = -2 }
}

В предыдущем примере шаблон var (x, y) эквивалентен позиционному шаблону (var x, var y).In the preceding example, pattern var (x, y) is equivalent to a positional pattern (var x, var y).

В шаблоне var тип объявленной переменной равен установленному во время компиляции типу выражения, сопоставляемого с данным шаблоном.In a var pattern, the type of a declared variable is the compile-time type of the expression that is matched against the pattern.

Дополнительные сведения см. в разделе Шаблон var в примечании к предлагаемой функции.For more information, see the Var pattern section of the feature proposal note.

Шаблон пустой переменнойDiscard pattern

Начиная с C# 8.0, шаблон пустой переменной _ используется для сопоставления любых выражений, включая null, как показано в следующем примере:Beginning with C# 8.0, you use a discard pattern _ to match any expression, including null, as the following example shows:

Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday));  // output: 5.0
Console.WriteLine(GetDiscountInPercent(null));  // output: 0.0
Console.WriteLine(GetDiscountInPercent((DayOfWeek)10));  // output: 0.0

static decimal GetDiscountInPercent(DayOfWeek? dayOfWeek) => dayOfWeek switch
{
    DayOfWeek.Monday => 0.5m,
    DayOfWeek.Tuesday => 12.5m,
    DayOfWeek.Wednesday => 7.5m,
    DayOfWeek.Thursday => 12.5m,
    DayOfWeek.Friday => 5.0m,
    DayOfWeek.Saturday => 2.5m,
    DayOfWeek.Sunday => 2.0m,
    _ => 0.0m,
};

В предыдущем примере шаблон пустой переменной используется для обработки значения null и любых целочисленных значений, которые не соответствуют имеющимся членам перечисления DayOfWeek.In the preceding example, a discard pattern is used to handle null and any integer value that doesn't have the corresponding member of the DayOfWeek enumeration. Благодаря этому гарантируется, что выражение switch в приведенном примере сможет обработать все возможные входные значения.That guarantees that a switch expression in the example handles all possible input values. Если в выражении switch не используется шаблон пустой переменной и при этом ни один из шаблонов выражения не соответствует входным данным, среда выполнения генерирует исключение.If you don't use a discard pattern in a switch expression and none of the expression's patterns matches an input, the runtime throws an exception. Если выражение switch не обрабатывает все возможные входные значения, компилятор генерирует предупреждение.The compiler generates a warning if a switch expression doesn't handle all possible input values.

Шаблон пустой переменной не может быть шаблоном в выражении is или операторе switch.A discard pattern cannot be a pattern in an is expression or a switch statement. В этих случаях для сопоставления выражений используйте шаблон var с пустой переменной: var _.In those cases, to match any expression, use a var pattern with a discard: var _.

Дополнительные сведения см. в разделе Шаблон пустой переменной в примечании к предлагаемой функции.For more information, see the Discard pattern section of the feature proposal note.

Шаблон в круглых скобкахParenthesized pattern

Начиная с C# 9.0, вы можете использовать круглые скобки вокруг любого шаблона.Beginning with C# 9.0, you can put parentheses around any pattern. Как правило, это делается для того, чтобы подчеркнуть или изменить приоритет логических шаблонов, как показано в следующем примере:Typically, you do that to emphasize or change the precedence in logical patterns, as the following example shows:

if (input is not (float or double))
{
    return;
}

Спецификация языка C#C# language specification

Дополнительные сведения см. в следующих примечаниях к предлагаемой функции.For more information, see the following feature proposal notes:

См. такжеSee also