Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Correspondência de padrões - as
Use a is expressão, a instrução switch e a expressão switch para corresponder uma expressão de entrada com qualquer número de características. O C# suporta vários padrões, incluindo declaração, tipo, constante, relacional, propriedade, lista, var e descarte. Pode combinar padrões usando as palavras-chave andda lógica booleana , or, e not.
A referência da linguagem C# documenta a versão mais recentemente lançada da linguagem C#. Contém também documentação inicial para funcionalidades em versões preliminares públicas para a próxima versão da linguagem.
A documentação identifica qualquer funcionalidade introduzida pela primeira vez nas últimas três versões da língua ou em pré-visualizações públicas atuais.
Gorjeta
Para saber quando uma funcionalidade foi introduzida pela primeira vez em C#, consulte o artigo sobre o histórico de versões da linguagem C#.
As seguintes expressões e instruções em C# oferecem suporte à correspondência de padrões:
Nessas construções, você pode fazer a correspondência de 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: desconstrua um resultado de expressão e teste se os valores resultantes correspondem a padrões aninhados.
-
varpattern: corresponda a qualquer expressão e atribua seu resultado a uma variável declarada. - Descartar padrão: corresponda a qualquer expressão.
- Padrões de lista: teste se uma sequência de elementos corresponde aos padrões aninhados correspondentes.
Padrões lógicos, de propriedade, posicionais e de lista são padrões recursivos . Ou seja, eles podem conter padrões aninhados .
Para um exemplo de como usar esses padrões para construir um algoritmo orientado por dados, veja Tutorial: Use pattern matching to build drivers algorithms baseados em tipos e dados.
Declaração e padrões de tipo
Use padrões de declaração e tipo para verificar se o tipo de execução de uma expressão é compatível com um dado 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, a variável é atribuída ao resultado da expressão convertida, como mostra o exemplo seguinte:
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 de tempo de execução de um resultado de expressão deriva do tipo
T, implementa a interfaceTou outra conversão de referência implícita existe dele paraT. Esta condição abrange relações de herança e implementações de interfaces. O exemplo a seguir demonstra dois casos em que essa condição é verdadeira:
No exemplo anterior, na primeira chamada para ovar 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, };GetSourceLabelmétodo, o primeiro padrão corresponde a um valor de argumento porque o tipoint[]de tempo de execução do argumento deriva do Array tipo. Na segunda chamada para oGetSourceLabelmétodo, o tipo List<T> de tempo de execução do argumento não deriva do Array tipo, mas implementa a ICollection<T> interface. - O tipo de tempo de execução de um resultado de expressão é um tipo de valor anulável com o tipo
Tsubjacente e 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 tipo
Tquando a expressão não é uma instância de umref struct.
Os padrões de declaração não consideram conversões definidas pelo usuário ou conversões de extensão 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
}
Para verificar apenas o tipo de expressão, use um descarte _ em vez do nome de uma variável, como mostra o exemplo seguinte:
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 esse fim, use um padrão tipográfico, como mostra o exemplo seguinte:
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 satisfaz qualquer uma das condições anteriores.
Para verificar se não é nulo, use umpadrão de constantenegadanull, como mostra o exemplo seguinte:
if (input is not null)
{
// ...
}
Para obter mais informações, consulte as seções Padrão de declaração e Padrão de tipo das notas de proposta de recurso.
Padrão constante
O padrão constante é uma sintaxe alternativa para == quando o operando certo é uma constante. Use um padrão constante para testar se um resultado de expressão é igual a uma constante especificada, como mostra o exemplo seguinte:
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 inteiro ou de vírgula flutuante
- um char
- um literal de corda
- um valor
truebooleano oufalse - um valor de enum
- o nome de um campo const declarado ou local
null
A expressão deve ser um tipo convertível para o tipo constante, com uma exceção: uma expressão cujo tipo é Span<char> ou ReadOnlySpan<char> pode ser comparado com cadeias constantes.
Use um padrão constante para verificar nullo , 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 é avaliada.
Você pode usar um padrão constante negadonull para verificar se não é nulo, como mostra o exemplo a seguir:
if (input is not null)
{
// ...
}
Para obter mais informações, consulte a seção Padrão constante da nota de proposta de recurso.
Padrões relacionais
Use um padrão relacional para comparar um resultado de expressão com uma constante, como mostra o exemplo seguinte:
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 relacionais , <, >, ou <=. A parte direita de um padrão relacional deve ser uma expressão constante. A expressão constante pode ser do tipo inteiro, ponto flutuante, char ou enum .
Para verificar se um resultado de expressão está em um determinado intervalo, faça a correspondência com um and conjuntivo, 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 convertido para o tipo de uma constante por uma conversão anulável ou 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 de proposta de recurso.
Padrões lógicos
Use os notcombinadores de padrões , and, e or para criar os seguintes padrões lógicos:
Padrão de
notnegação que corresponde a uma expressão quando o padrão negado 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) { // ... }Padrão conjuntivo
andque 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", };Padrão disjuntivo
orque corresponde a uma expressão quando qualquer 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 de controlo
Os combinadores de padrões seguem esta ordem, baseada na ordem de ligação das expressões:
notandor
O not padrão liga-se primeiro ao seu operando. O and padrão liga-se após qualquer not ligação de expressão de padrão. O or padrão liga-se, afinal not , e and os padrões ligam-se aos operandos. O exemplo seguinte tenta associar todos os caracteres que não são letras minúsculas, a - z. Ele tem um erro, porque o not padrão se liga antes do and padrão:
// 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 corrigir o erro, especifique que quer que o not padrão se associe à >= 'a' and <= 'z' expressão:
// Correct pattern. Force `and` before `not`
static bool IsNotLowerCaseLetterParentheses(char c) => c is not (>= 'a' and <= 'z');
Adicionar parênteses torna-se mais importante à medida que os seus padrões se tornam mais complicados. Em geral, use parênteses para esclarecer 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');
Nota
A ordem na qual os padrões com a mesma ordem de vinculação são verificados é indefinida. Em tempo de execução, os padrões aninhados à direita de vários or padrões e vários and padrões podem ser verificados primeiro.
Para obter mais informações, consulte a seção Combinadores de padrões da nota de proposta de recurso.
Padrão de propriedade
Use um padrão de propriedades para comparar as propriedades ou campos de uma expressão com padrões aninhados, como mostra o exemplo seguinte:
static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };
Um padrão de propriedades corresponde a uma expressão quando o resultado da expressão não é nulo e cada padrão aninhado corresponde à propriedade ou campo correspondente do resultado da expressão.
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 seguinte:
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."),
};
Este construto significa especificamente que o padrão is { }de propriedades vazias corresponde a tudo o que não é nulo, e pode usá-lo em vez de is not null para 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 um padrão aninhado. Use um padrão de propriedade para fazer a correspondência entre partes de dados e 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 combinador de padrões e os ortipos de registro.
Você pode fazer referência a propriedades ou campos aninhados dentro de um padrão de propriedade. Esse recurso é conhecido como um padrão de propriedade estendida. Por exemplo, você pode refatorar o método do exemplo anterior no 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 de recurso e a nota de proposta de recurso Padrões de propriedade estendidos.
Gorjeta
Para melhorar a legibilidade do código, utilize a regra do estilo Simplificar padrão de propriedades (IDE0170). Sugere locais para usar padrões de propriedades estendidos.
Padrão posicional
Use um padrão posicional para desconstruir uma expressão e comparar os valores resultantes com os padrões aninhados correspondentes, como mostra o exemplo seguinte:
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 uma expressão contém o método de Desconstrução , que o padrão usa para desconstruir um resultado de expressão.
Importante
A ordem dos membros em um padrão posicional deve corresponder à Deconstruct ordem dos parâmetros no método. O código gerado para o padrão posicional chama o Deconstruct método.
Você também pode combinar expressões de tipos de tupla com padrões posicionais. Ao usar esta abordagem, pode comparar múltiplos inputs com vários padrões, como mostra o exemplo seguinte:
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 e Deconstruct parâmetros de tupla 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 em 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 implicitamente fornecem o
Deconstructmétodo.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 um padrão aninhado.
Para obter mais informações, consulte a seção Padrão posicional da nota de proposta de recurso.
var padrão
Use um var padrão para corresponder a qualquer expressão, incluindo null, e atribua o seu resultado a uma nova variável local, como mostra o exemplo seguinte:
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 var padrão é útil quando você precisa de uma variável temporária dentro de uma expressão booleana para manter o resultado de cálculos intermediários. Você também pode usar um var padrão quando precisar executar mais verificações em when protetores de caso de uma switch expressão ou instrução, 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(var x, var y)posicional.
Num var padrão, o tipo de uma variável declarada é o tipo em tempo de compilação da expressão que o padrão corresponde.
Para obter mais informações, consulte a seção Padrão Var da nota de proposta de recurso.
Padrão de descarte
Use um padrão _de descarte para corresponder a qualquer expressão, incluindo null, como mostra o exemplo seguinte:
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 manipula null e qualquer valor inteiro que não tenha o membro correspondente da DayOfWeek enumeração. Essa garantia garante que uma switch expressão no exemplo gere todos os valores de entrada possíveis. Se você não usar um padrão de descarte em uma switch expressão e nenhum dos padrões da expressão corresponder a uma entrada, o tempo de execução lançará uma exceção. O compilador gera um aviso se uma switch expressão não manipular todos os valores de entrada possíveis.
Um padrão de descarte não pode ser um padrão em uma is expressão ou 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 pode ser um padrão em uma switch expressão.
Para obter mais informações, consulte a seção Descartar padrão da nota de proposta de 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
Pode comparar um array ou uma lista com uma sequência de padrões, como mostra o exemplo seguinte:
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 corresponde ao momento em que cada padrão aninhado corresponde ao 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 de descarte ou, se também quiser capturar o elemento, use o padrão var, como mostra o exemplo seguinte:
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 com um padrão de lista. Para corresponder elementos somente no início e/ou no final de uma sequência de entrada, use o padrão..de fatia , como mostra o exemplo a seguir:
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, consulte a Observação de proposta de recurso Listar padrões .
Especificação da linguagem C#
Para obter mais informações, consulte a seção Padrões e correspondência de padrões da especificação da linguagem C#.
Para informações sobre funcionalidades adicionadas em C# 9 e versões posteriores, consulte as seguintes notas de proposta de funcionalidades:
- Atualizações de correspondência de padrões
- Padrões de propriedade estendidos
- Padrões de lista
-
Correspondência
Span<char>de padrão no literal da corda