Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Padrões correspondentes: expressões
Você usa a expressão is, a instrução = switch instrução switch e a expressão switch para comparar uma expressão de entrada com qualquer número de características. O C# dá suporte a vários padrões, incluindo declaração, tipo, constante, relacional, propriedade, lista, var e descarte. Os padrões podem ser combinados usando palavras-chave da lógica booliana and, or e not.
As seguintes expressões e instruções C# dão suporte à correspondência de padrões:
Nesses constructos, você pode corresponder uma expressão de entrada com qualquer um dos seguintes padrões:
- Padrão de declaração: verifique o tipo de tempo de execução de uma expressão e, se uma correspondência for bem-sucedida, atribua um resultado de expressão a uma variável declarada.
- Padrão de tipo: verifique o tipo de tempo de execução de uma expressão.
- Padrão constante: teste se um resultado de expressão é igual a uma constante especificada.
- Padrões relacionais: compare um resultado de expressão com uma constante especificada.
- Padrões lógicos: teste se uma expressão corresponde a uma combinação lógica de padrões.
- Padrão de propriedade: teste se as propriedades ou campos de uma expressão correspondem a padrões aninhados.
- Padrão posicional: desconstruir um resultado de expressão e testar se os valores resultantes correspondem a padrões aninhados.
-
varpadrão: corresponder a qualquer expressão e atribuir seu resultado a uma variável declarada. - Descartar padrão: para corresponder a qualquer expressão.
- Padrões de lista: teste se uma sequência de elementos corresponde aos padrões aninhados correspondentes.
Logical, property, positional e list são padrões recursivos. Ou seja, eles podem conter padrões aninhados.
Para obter o exemplo de como usar esses padrões para criar um algoritmo controlado por dados, consulte Tutorial: Usar a correspondência de padrões para criar algoritmos controlados por tipo e controlados por dados.
Padrões de declaração e tipo
Você usa padrões de declaração e tipo para verificar se o tipo de tempo de execução de uma expressão é compatível com um determinado tipo. Com um padrão de declaração, você também pode declarar uma nova variável local. Quando um padrão de declaração corresponde a uma expressão, essa variável é atribuída ao resultado da expressão convertida, como mostra o exemplo a seguir:
object greeting = "Hello, World!";
if (greeting is string message)
{
Console.WriteLine(message.ToLower()); // output: hello, world!
}
Um padrão de declaração com tipo T corresponde a uma expressão quando um resultado de expressão não é nulo e qualquer uma das seguintes condições é verdadeira:
- O tipo de tempo de execução de um resultado de expressão tem uma conversão de identidade para
T. - O tipo
Té umref structtipo e há uma conversão de identidade da expressão paraT. - O tipo do resultado de uma expressão em tempo de execução deriva do tipo
T, implementa a interfaceTou existe outra conversão de referência implícita dele paraT. Isso aborda relações de herança e implementações de interface. O exemplo a seguir demonstra dois casos em que essa condição é verdadeira:
No exemplo anterior, na primeira chamada ao métodovar 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, o primeiro padrão corresponde a um valor de argumento porque o tipoint[]de tempo de execução do argumento deriva do tipo Array. Na segunda chamada para o métodoGetSourceLabel, o tipo List<T> de tempo de execução do argumento não deriva do tipo Array, mas implementa a interface ICollection<T>. - O tipo do resultado de uma expressão em tempo de execução é um tipo de valor anulável com o tipo subjacente
Te o Nullable<T>.HasValue étrue. - Existe uma conversão de boxing ou unboxing do tipo de tempo de execução de um resultado de expressão para o tipo
Tquando a expressão não é uma instância deref struct.
Os padrões de declaração não consideram conversões definidas pelo usuário ou conversões de intervalo implícitas.
O exemplo a seguir demonstra as duas últimas condições:
int? xNullable = 7;
int y = 23;
object yBoxed = y;
if (xNullable is int a && yBoxed is int b)
{
Console.WriteLine(a + b); // output: 30
}
Se você quiser verificar apenas o tipo de uma expressão, poderá usar um descarte _ no lugar do nome de uma variável, como mostra o exemplo a seguir:
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)),
};
}
Para essa finalidade, você pode usar um padrão de tipo, conforme mostrado no seguinte exemplo:
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)),
};
Como um padrão de declaração, um padrão de tipo corresponde a uma expressão quando um resultado de expressão não é nulo e seu tipo de tempo de execução atende a qualquer uma das condições listadas acima.
Para verificar se há não nulo, você pode usar um padrão constante negadonull, como mostra o exemplo a seguir:
if (input is not null)
{
// ...
}
Para obter mais informações, consulte as seções padrão declaração e padrão de tipo das notas de proposta do recurso.
Padrão de constante
O padrão constante é uma sintaxe alternativa para == quando o operando à direita é uma constante. Você usa um padrão constante para testar se um resultado de expressão é igual a uma constante especificada, como mostra o exemplo a seguir:
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)),
};
Em um padrão constante, você pode usar qualquer expressão constante, como:
- um literal numérico de inteiro ou ponto flutuante
- um char
- um literal de cadeia de caracteres.
- um valor booliano
trueoufalse - um valor enum
- o nome de um campo const declarado ou local
null
A expressão deve ser um tipo conversível para o tipo constante, com uma exceção: uma expressão cujo tipo é Span<char> ou ReadOnlySpan<char> pode ser correspondido com cadeias de caracteres constantes.
Use um padrão constante para verificar null, como mostra o exemplo a seguir:
if (input is null)
{
return;
}
O compilador garante que nenhum operador de igualdade sobrecarregado pelo usuário == seja invocado quando a expressão x is null for avaliada.
Use um padrão de constante negadonull para verificar se ele não é nulo, conforme mostrado no seguinte exemplo:
if (input is not null)
{
// ...
}
Para obter mais informações, consulte a seção Padrão constante da nota da proposta do recurso.
Padrões relacionais
Use um padrão relacional para comparar um resultado de expressão com uma constante, conforme mostrado no seguinte exemplo:
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",
};
Em um padrão relacional, você pode usar qualquer um dos operadores relacionais<, >, <= ou >=. A parte direita de um padrão relacional deve ser uma expressão constante. A expressão constante pode ser de um tipo inteiro, ponto flutuante, char ou enumerado.
Para verificar se um resultado de expressão está em um determinado intervalo, corresponda-o a um padrão conjuntivoand, como mostra o exemplo a seguir:
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}."),
};
Se um resultado de expressão for null ou não for convertido no tipo de uma constante por uma conversão anulável ou de unboxing, um padrão relacional não corresponderá a uma expressão.
Para obter mais informações, consulte a seção Padrões relacionais da nota da proposta do recurso.
Padrões lógicos
Use os combinadores de padrões not, and e or para criar os seguintes padrões lógicos:
Negação
notpadrão que corresponde a uma expressão quando o padrão negated não corresponde à expressão. O exemplo a seguir mostra como você pode negar um padrão constantenullpara verificar se uma expressão não é nula:if (input is not null) { // ... }Conjuntivo
andpadrão que corresponde a uma expressão quando ambos os padrões correspondem à expressão. O exemplo a seguir mostra como você pode combinar padrões relacionais para verificar se um valor está em um determinado intervalo: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", };Disjuntivo
orpadrão que corresponde a uma expressão quando um dos padrões corresponde à expressão, como mostra o exemplo a seguir: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}."), };
Como mostra o exemplo anterior, você pode usar repetidamente os combinadores de padrão em um padrão.
Precedência e ordem da avaliação
Os combinadores de padrões são ordenados com base na ordem de associação das expressões da seguinte maneira:
notandor
O padrão not é associado ao seu operando primeiro. O padrão and é associado após qualquer not associação de expressão padrão. O padrão or é associado após todos os padrões not e and serem associados aos operandos. O exemplo a seguir tenta corresponder a todos os caracteres que não são letras minúsculas, a - z. Ele tem um erro, porque o padrão not é vinculado antes do and:
// Incorrect pattern. `not` binds before `and`
static bool IsNotLowerCaseLetter(char c) => c is not >= 'a' and <= 'z';
A associação padrão significa que o exemplo anterior é analisado como o exemplo a seguir:
// The default binding without parentheses is shows in this method. `not` binds before `and`
static bool IsNotLowerCaseLetterDefaultBinding(char c) => c is ((not >= 'a') and <= 'z');
Para corrigi-lo, você deve especificar que deseja que o not se associe à expressão >= 'a' and <= 'z':
// Correct pattern. Force `and` before `not`
static bool IsNotLowerCaseLetterParentheses(char c) => c is not (>= 'a' and <= 'z');
Adicionar parênteses fica mais importante à medida que os padrões se tornam mais complicados. Em geral, use parênteses para clarificar seus padrões para outros desenvolvedores, como mostra o exemplo a seguir:
static bool IsLetter(char c) => c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z');
Observação
A ordem na qual os padrões com a mesma ordem de associação são verificados é indefinida. No tempo de execução, os padrões aninhados à direita dos múltiplos or e múltiplos and podem ser verificados primeiro.
Para obter mais informações, consulte a seção Padrão constante da nota da proposta do recurso.
Padrão de propriedade
Você usa um padrão de propriedade para corresponder às propriedades ou campos de uma expressão com padrões aninhados, como mostra o exemplo a seguir:
static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };
Um padrão de propriedade corresponde a uma expressão quando um resultado de expressão não é nulo e cada padrão aninhado corresponde à propriedade ou campo correspondente do resultado da expressão.
Você também pode adicionar uma verificação de tipo em tempo de execução e uma declaração de variável a um padrão de propriedade, como mostra o exemplo a seguir:
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."),
};
Esse constructo significa especificamente que o padrão is { } de propriedade vazio corresponde a tudo que não é nulo e pode ser usado em vez de is not null criar uma variável: somethingPossiblyNull is { } somethingDefinitelyNotNull.
if (GetSomeNullableStringValue() is { } nonNullValue) // Empty property pattern with variable creation
{
Console.WriteLine("NotNull:" + nonNullValue);
}
else
{
nonNullValue = "NullFallback"; // we can access the variable here.
Console.WriteLine("it was null, here's the fallback: " + nonNullValue);
}
Um padrão de propriedade é um padrão recursivo. Você pode usar qualquer padrão como aninhado. Use um padrão de propriedade para corresponder partes de dados com padrões aninhados, como mostra o exemplo a seguir:
public record Point(int X, int Y);
public record Segment(Point Start, Point End);
static bool IsAnyEndOnXAxis(Segment segment) =>
segment is { Start: { Y: 0 } } or { End: { Y: 0 } };
O exemplo anterior usa o orcombinador de padrões e os tipos de registro.
Você pode referenciar propriedades aninhadas ou campos dentro de um padrão de propriedade. Essa capacidade é conhecida como um padrão de propriedade estendido. Por exemplo, você pode refatorar o método do exemplo anterior para o seguinte código equivalente:
static bool IsAnyEndOnXAxis(Segment segment) =>
segment is { Start.Y: 0 } or { End.Y: 0 };
Para obter mais informações, consulte a seção Padrão de propriedade da nota de proposta do recurso e a nota de proposta de recurso Padrões de propriedade estendida.
Dica
Você pode usar a regra de estilo Simplificar padrão de propriedade (IDE0170) para melhorar a legibilidade do código sugerindo locais para usar padrões de propriedade estendidos.
Padrão posicional
Você usa um padrão posicional para desconstruir um resultado de expressão e corresponder aos valores resultantes com os padrões aninhados correspondentes, como mostra o exemplo a seguir:
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",
};
No exemplo anterior, o tipo de expressão contém o método Deconstruct, que é usado para desconstruir um resultado de expressão.
Importante
A ordem dos membros em um padrão posicional deve corresponder à ordem dos parâmetros no método Deconstruct. O código gerado para o padrão posicional chama o Deconstruct método.
Você também pode corresponder expressões de tipos de tupla com padrões posicionais. Dessa forma, você pode corresponder várias entradas com vários padrões, como mostra o exemplo a seguir:
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,
};
O exemplo anterior usa padrões relacionais e lógicos.
Você pode usar os nomes de elementos de tupla e parâmetros Deconstruct em um padrão posicional, como mostra o exemplo a seguir:
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);
}
Você também pode estender um padrão posicional de qualquer uma das seguintes maneiras:
Adicione uma verificação de tipo de tempo de execução e uma declaração de variável, como mostra o exemplo a seguir:
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, };O exemplo anterior usa registros posicionais que fornecem implicitamente o método
Deconstruct.Use um padrão de propriedade dentro de um padrão posicional, como mostra o exemplo a seguir:
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 dois usos anteriores, como mostra o exemplo a seguir:
if (input is WeightedPoint (> 0, > 0) { Weight: > 0.0 } p) { // .. }
Um padrão posicional é um padrão recursivo. Ou seja, você pode usar qualquer padrão como aninhado.
Para obter mais informações, consulte a seção Padrão constante da nota da proposta do recurso.
var padrão
Você usa um var padrão para corresponder a qualquer expressão, incluindo null, e atribuir seu resultado a uma nova variável local, como mostra o exemplo a seguir:
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();
}
Um padrão var é útil quando você precisa de uma variável temporária dentro de uma expressão booliana para manter o resultado de cálculos intermediários. Você também poderá usar um padrão var quando precisar realizar mais verificações em proteções de caso when de uma expressão ou instrução switch, como mostra o exemplo a seguir:
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 }
}
No exemplo anterior, o padrão var (x, y) é equivalente a um padrão posicional(var x, var y).
Em um padrão var, o tipo de uma variável declarada é o tipo de tempo de compilação da expressão que corresponde ao padrão.
Para obter mais informações, consulte a seção Padrão constante da nota da proposta do recurso.
Padrão de descarte
Você usa um padrão de descarte_ para corresponder a qualquer expressão, incluindo null, conforme mostra o exemplo a seguir:
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,
};
No exemplo anterior, um padrão de descarte é usado para tratar null e qualquer valor inteiro que não tenha o membro correspondente da enumeração DayOfWeek. Isso garante que uma expressão switch no exemplo manipule todos os valores de entrada possíveis. Se você não usar um padrão de descarte em uma expressão switch e nenhum dos padrões da expressão corresponder a uma entrada, o runtime gerará uma exceção. O compilador gera um aviso se uma expressão switch não manipular todos os valores de entrada possíveis.
Um padrão de descarte não pode ser um padrão em uma expressão is ou uma instrução switch. Nesses casos, para corresponder a qualquer expressão, use um var padrão com um descarte: var _. Um padrão de descarte não pode ser um padrão em uma switch expressão.
Para obter mais informações, consulte a seção Padrão constante da nota da proposta do recurso.
Padrão entre parênteses
Você pode colocar parênteses em torno de qualquer padrão. Normalmente, você faz isso para enfatizar ou alterar a precedência em padrões lógicos, como mostra o exemplo a seguir:
if (input is not (float or double))
{
return;
}
Padrões de lista
Você pode corresponder uma matriz ou uma lista com uma sequência de padrões, como mostra o exemplo a seguir:
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers is [1, 2, 3]); // True
Console.WriteLine(numbers is [1, 2, 4]); // False
Console.WriteLine(numbers is [1, 2, 3, 4]); // False
Console.WriteLine(numbers is [0 or 1, <= 2, >= 3]); // True
Como mostra o exemplo anterior, um padrão de lista é correspondido quando cada padrão aninhado é correspondido pelo elemento correspondente de uma sequência de entrada. Você pode usar qualquer padrão dentro de um padrão de lista. Para corresponder a qualquer elemento, use o padrão discard ou, se você também quiser capturar o elemento, o padrão var, como mostra o exemplo a seguir:
List<int> numbers = new() { 1, 2, 3 };
if (numbers is [var first, _, _])
{
Console.WriteLine($"The first element of a three-item list is {first}.");
}
// Output:
// The first element of a three-item list is 1.
Os exemplos anteriores correspondem a uma sequência de entrada inteira em relação a um padrão de lista. Para corresponder elementos somente no início ou/e no final de uma sequência de entrada, use o padrão de fatia.. como mostra o seguinte exemplo:
Console.WriteLine(new[] { 1, 2, 3, 4, 5 } is [> 0, > 0, ..]); // True
Console.WriteLine(new[] { 1, 1 } is [_, _, ..]); // True
Console.WriteLine(new[] { 0, 1, 2, 3, 4 } is [> 0, > 0, ..]); // False
Console.WriteLine(new[] { 1 } is [1, 2, ..]); // False
Console.WriteLine(new[] { 1, 2, 3, 4 } is [.., > 0, > 0]); // True
Console.WriteLine(new[] { 2, 4 } is [.., > 0, 2, 4]); // False
Console.WriteLine(new[] { 2, 4 } is [.., 2, 4]); // True
Console.WriteLine(new[] { 1, 2, 3, 4 } is [>= 0, .., 2 or 4]); // True
Console.WriteLine(new[] { 1, 0, 0, 1 } is [1, 0, .., 0, 1]); // True
Console.WriteLine(new[] { 1, 0, 1 } is [1, 0, .., 0, 1]); // False
Um padrão de fatia corresponde a zero ou mais elementos. Você pode usar no máximo um padrão de fatia em um padrão de lista. O padrão de fatia só pode aparecer em um padrão de lista.
Você também pode aninhar um subpadrão dentro de um padrão de fatia, como mostra o exemplo a seguir:
void MatchMessage(string message)
{
var result = message is ['a' or 'A', .. var s, 'a' or 'A']
? $"Message {message} matches; inner part is {s}."
: $"Message {message} doesn't match.";
Console.WriteLine(result);
}
MatchMessage("aBBA"); // output: Message aBBA matches; inner part is BB.
MatchMessage("apron"); // output: Message apron doesn't match.
void Validate(int[] numbers)
{
var result = numbers is [< 0, .. { Length: 2 or 4 }, > 0] ? "valid" : "not valid";
Console.WriteLine(result);
}
Validate(new[] { -1, 0, 1 }); // output: not valid
Validate(new[] { -1, 0, 0, 1 }); // output: valid
Para obter mais informações, confira a nota de proposta de recursos de Padrões de lista.
Especificação da linguagem C#
Para obter mais informações, confira a seção Padrões e padrões correspondentes da especificação da linguagem C#.
Para informações sobre os recursos adicionados ao C# 8 e versões posteriores, confira as seguintes notas sobre a proposta de recursos:
- Atualizações sobre padrões correspondentes
- Padrões de Propriedade Estendidos
- Padrões de lista
-
Correspondência de
Span<char>padrão no literal de cadeia de caracteres