Comparteix via


Coincidencia de patrones: las expresiones is y switch y los operadores and, or y not en patrones.

Use la is expresión, la instrucción switch y la expresión switch para que coincida con una expresión de entrada con cualquier número de características. C# admite varios patrones, como declaración, tipo, constante, relacional, propiedad, lista, var y descarte. Puede combinar patrones mediante las palabras clave lógica booleanas and, ory not.

La documentación de referencia del lenguaje C# cubre la versión más reciente publicada del lenguaje C#. También contiene documentación inicial sobre las características de las versiones preliminares públicas de la próxima versión del lenguaje.

La documentación identifica cualquier característica introducida por primera vez en las últimas tres versiones del idioma o en las versiones preliminares públicas actuales.

Sugerencia

Para buscar cuándo se introdujo por primera vez una característica en C#, consulte el artículo sobre el historial de versiones del lenguaje C#.

Las siguientes expresiones e instrucciones de C# admiten la coincidencia de patrones:

En esas construcciones, puede hacer coincidir una expresión de entrada con cualquiera de los siguientes patrones:

  • Patrón de declaración: verifica el tipo de una expresión en tiempo de ejecución y, si la coincidencia es exitosa, asigna el resultado de la expresión a una variable declarada.
  • Patrón de tipo: compruebe el tipo en tiempo de ejecución de una expresión.
  • Patrón constante: pruebe que un resultado de expresión es igual a una constante especificada.
  • Patrones relacionales: compare un resultado de expresión con una constante especificada.
  • Patrones lógicos: pruebe que una expresión coincide con una combinación lógica de patrones.
  • Patrón de propiedad: pruebe que las propiedades o campos de una expresión coinciden con patrones anidados.
  • Patrón posicional: deconstruye un resultado de expresión y prueba si los valores resultantes coinciden con patrones anidados.
  • var pattern: coincide con cualquier expresión y asigna su resultado a una variable declarada.
  • Descartar patrón: coincide con cualquier expresión.
  • Patrones de lista: pruebe que una secuencia de elementos coincide con los patrones anidados correspondientes.

Los patrones lógicos, de propiedad, posicionales y de lista son patrones recursivos. Es decir, pueden contener patrones anidados.

Para obtener un ejemplo de cómo usar esos patrones para crear un algoritmo controlado por datos, consulte Tutorial: Uso de la coincidencia de patrones para crear algoritmos controlados por tipos y controlados por datos.

Patrones de declaración y de tipo

Use patrones de declaración y tipo para comprobar si el tipo en tiempo de ejecución de una expresión es compatible con un tipo determinado. Con un patrón de declaración, también puede declarar una nueva variable local. Cuando un patrón de declaración coincide con una expresión, la variable se asigna al resultado de la expresión convertida, como se muestra en el ejemplo siguiente:

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

Un patrón de declaración con el tipo T coincide con una expresión cuando el resultado de una expresión no es NULL y se cumple cualquiera de las condiciones siguientes:

  • El tipo en tiempo de ejecución de un resultado de expresión tiene una conversión de identidad a T.
  • El tipo T es un ref struct tipo y hay una conversión de identidad de la expresión a T.
  • El tipo en tiempo de ejecución del resultado de una expresión deriva del tipo T, implementa una interfaz T, o bien otra conversión de referencia implícita existe en T. Esta condición cubre las relaciones de herencia y las implementaciones de interfaz. En el ejemplo siguiente se muestran dos casos en los que esta condición es verdadera:
    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,
    };
    
    En el ejemplo anterior, en la primera llamada al método GetSourceLabel, el primer patrón coincide con un valor de argumento porque el tipo en tiempo de ejecución int[] del argumento deriva del tipo Array. En la segunda llamada al método GetSourceLabel, el tipo en tiempo de ejecución List<T> del argumento no deriva del tipo Array, pero implementa la interfaz ICollection<T>.
  • El tipo en tiempo de ejecución del resultado de una expresión es un tipo de valor que admite un valor NULL con el tipo subyacente T y Nullable<T>.HasValue es true.
  • Existe una conversión boxing o unboxing del tipo en tiempo de ejecución de un resultado de expresión al tipo T cuando la expresión no es una instancia de ref struct.

Los patrones de declaración no tienen en cuenta las conversiones definidas por el usuario ni las conversiones de intervalo implícita.

En el ejemplo siguiente se muestran las dos últimas condiciones:

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 comprobar solo el tipo de una expresión, use un descarte _ en lugar del nombre de una variable, como se muestra en el ejemplo siguiente:

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 ello, use un patrón de tipo, como se muestra en el ejemplo siguiente:

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)),
};

Al igual que un patrón de declaración, un patrón de tipo coincide con una expresión cuando el resultado de una expresión no es NULL y su tipo en tiempo de ejecución cumple cualquiera de las condiciones mencionadas anteriormente.

Para comprobar si no es NULL, use unpatrón de constantenegadanull, como se muestra en el ejemplo siguiente:

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

Para obtener más información, vea las secciones Patrón de declaración y Patrón de tipo de las notas de propuesta de características.

Patrón de constante

El patrón constante es una sintaxis alternativa para == cuando el operando derecho es una constante. Use un patrón constante para probar si un resultado de expresión es igual a una constante especificada, como se muestra en el ejemplo siguiente:

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)),
};

En un patrón de constante, se puede usar cualquier expresión constante, como:

La expresión debe ser un tipo que se puede convertir en el tipo constante, con una excepción: una expresión cuyo tipo es Span<char> o ReadOnlySpan<char> puede coincidir con cadenas constantes.

Use un patrón de constante para comprobar null, como se muestra en el ejemplo siguiente:

if (input is null)
{
    return;
}

El compilador garantiza que no se invoca ningún operador de igualdad sobrecargado por el usuario == cuando se evalúa la expresión x is null.

Puede usar un patrón de constantes negadasnull para comprobar si no son NULL, como se muestra en el ejemplo siguiente:

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

Para obtener más información, vea la sección Patrón de constante de la nota de propuesta de características.

Patrones relacionales

Use un patrón relacional para comparar un resultado de expresión con una constante, como se muestra en el ejemplo siguiente:

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",
};

En un patrón relacional, se puede usar cualquiera de los operadores relacionales<, >, <=, o >=. La parte derecha de un patrón relacional debe ser una expresión constante. La expresión constante puede ser de tipo entero, de punto flotante, de carácter o de enumeración.

Para comprobar si el resultado de una expresión está en un intervalo determinado, busque coincidencias con un patrón conjuntivo and, como se muestra en el ejemplo siguiente:

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}."),
};

Si el resultado de una expresión es null o no se puede convertir al tipo de una constante mediante una conversión que acepta valores NULL o unboxing, un patrón relacional no coincide con una expresión.

Para obtener más información, vea la sección Patrones relacionales de la nota de propuesta de características.

Patrones lógicos

Use los notcombinadores de patrones , andy or para crear los siguientes patrones lógicos:

  • Patrón de negaciónnot que coincide con una expresión cuando el patrón negado no coincide con ella. En el ejemplo siguiente se muestra cómo se puede negar un patrón constantenull para comprobar si una expresión no es null:

    if (input is not null)
    {
        // ...
    }
    
  • Patrón conjuntivoand que coincide con una expresión cuando ambos patrones coinciden con ella. En el ejemplo siguiente se muestra cómo se pueden combinar patrones relacionales para comprobar si un valor se encuentra en un intervalo determinado:

    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",
    };
    
  • Patrón disyuntivoor que coincide con una expresión cuando uno de los patrones coincide con ella, como se muestra en el ejemplo siguiente:

    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 se muestra en el ejemplo anterior, se puede usar repetidamente los combinadores de patrones en un patrón.

Precedencia y orden de comprobación

Los combinadores de patrones siguen este orden, en función del orden de enlace de las expresiones:

  • not
  • and
  • or

El patrón not se enlaza primero a su operando. El patrón and se enlaza después de cualquier enlace de expresión de patrón not.. El or patrón se enlaza después de que todos los not patrones y and se enlazan a operandos. En el ejemplo siguiente se intenta hacer coincidir todos los caracteres que no son letras minúsculas, a - z. Tiene un error, porque el patrón not se enlaza antes del patrón and:

// Incorrect pattern. `not` binds before `and`
static bool IsNotLowerCaseLetter(char c) => c is not >= 'a' and <= 'z';

El enlace predeterminado significa que el ejemplo anterior se analiza como el ejemplo siguiente:

// 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 corregir el error, especifique que desea que el not patrón se enlace a la >= 'a' and <= 'z' expresión:

// Correct pattern. Force `and` before `not`
static bool IsNotLowerCaseLetterParentheses(char c) => c is not (>= 'a' and <= 'z');

Agregar paréntesis se vuelve más importante a medida que los patrones se vuelven más complicados. En general, use paréntesis para aclarar los patrones de otros desarrolladores, como se muestra en el ejemplo siguiente:

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

Nota

El orden en el que se comprueban los patrones que tienen el mismo orden de enlace no está definido. En tiempo de ejecución, se pueden comprobar primero los patrones anidados del lado derecho de los patrones or múltiples y and múltiples.

Para obtener más información, vea la sección Combinadores de patrones de la nota de propuesta de características.

Patrón de propiedad

Use un patrón de propiedad para hacer coincidir las propiedades o campos de una expresión con patrones anidados, como se muestra en el ejemplo siguiente:

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

Un patrón de propiedad coincide con una expresión cuando el resultado de la expresión no es NULL y cada patrón anidado coincide con la propiedad o campo correspondientes del resultado de la expresión.

Puede agregar una comprobación de tipo en tiempo de ejecución y una declaración de variable a un patrón de propiedad, como se muestra en el ejemplo siguiente:

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."),
};

Esta construcción significa específicamente que el patrón is { } de propiedad vacío coincide con todo lo que no es NULL y puede usarlo en lugar de is not null para crear una variable: 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);
}

Un patrón de propiedad es un patrón recursivo. Se puede usar cualquier patrón como patrón anidado. Use un patrón de propiedad para hacer coincidir partes de los datos con patrones anidados, como se muestra en el ejemplo siguiente:

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 } };

En el ejemplo anterior se usa el orcombinador de patrones y los tipos de registro.

Puede hacer referencia a propiedades o campos anidados dentro de un patrón de propiedades. Esta funcionalidad se conoce como patrón de propiedad extendida. Por ejemplo, puede refactorizar el método del ejemplo anterior en el código equivalente siguiente:

static bool IsAnyEndOnXAxis(Segment segment) =>
    segment is { Start.Y: 0 } or { End.Y: 0 };

Para obtener más información, consulte la sección Patrón de propiedad de la nota de propuesta de características y la nota de propuesta de características Patrones de propiedades extendidos.

Sugerencia

Para mejorar la legibilidad del código, use la regla de estilo Simplificar patrón de propiedades (IDE0170). Sugiere lugares para usar patrones de propiedad extendidos.

Patrón posicional

Use un patrón posicional para deconstruir una expresión y hacer coincidir los valores resultantes con los patrones anidados correspondientes, como se muestra en el ejemplo siguiente:

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",
};

En el ejemplo anterior, el tipo de una expresión contiene el método Deconstruct , que el patrón usa para deconstruir un resultado de expresión.

Importante

El orden de los miembros de un patrón posicional debe coincidir con el orden de los parámetros del método Deconstruct. El código generado para el patrón posicional llama al Deconstruct método .

También puede hacer coincidir expresiones de tipos de tupla con patrones posicionales. Con este enfoque, puede hacer coincidir varias entradas con varios patrones, como se muestra en el ejemplo siguiente:

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,
    };

En el ejemplo anterior se usan patrones relacionales y lógicos.

Puede usar los nombres de elementos de tupla y parámetros Deconstruct en un patrón posicional, como se muestra en el ejemplo siguiente:

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);
}

También puede extender un patrón posicional de cualquiera de las siguientes maneras:

  • Agregue una comprobación de tipo en tiempo de ejecución y una declaración de variable, como se muestra en el ejemplo siguiente:

    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,
    };
    

    En el ejemplo anterior se usan registros posicionales que proporcionan implícitamente el método Deconstruct.

  • Use un patrón de propiedad dentro de un patrón posicional, como se muestra en el ejemplo siguiente:

    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 dos usos anteriores, como se muestra en el ejemplo siguiente:

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

Un patrón posicional es un patrón recursivo. Es decir, se puede usar cualquier patrón como patrón anidado.

Para obtener más información, vea la sección Patrón posicional de la nota de propuesta de características.

var patrón

Use un var patrón para que coincida con cualquier expresión, incluido null, y asigne su resultado a una nueva variable local, como se muestra en el ejemplo siguiente:

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();
}

Un patrón var es útil cuando se necesita una variable temporal dentro de una expresión booleana para contener el resultado de los cálculos intermedios. También se puede usar un patrón var cuando necesite realizar comprobaciones adicionales en las restricciones de mayúsculas y minúsculas when de una expresión o instrucción switch, como se muestra en el ejemplo siguiente:

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 }
}

En el ejemplo anterior, el patrón var (x, y) es equivalente a un patrón posicional(var x, var y).

En un var patrón, el tipo de una variable declarada es el tipo en tiempo de compilación de la expresión que coincide con el patrón.

Para obtener más información, vea la sección Patrón Var de la nota de propuesta de características.

Patrón de descarte

Use un patrón_ de descarte para que coincida con cualquier expresión, incluido null, como se muestra en el ejemplo siguiente:

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,
};

En el ejemplo anterior, un patrón de descarte controla null y cualquier valor entero que no tenga el miembro correspondiente de la DayOfWeek enumeración. Esa garantía garantiza que una switch expresión del ejemplo controla todos los valores de entrada posibles. Si no se usa un patrón de descarte en una expresión switch y ninguno de los patrones de la expresión coincide con una entrada, el tiempo de ejecución produce una excepción. El compilador genera una advertencia si una expresión switch no controla todos los valores de entrada posibles.

Un patrón de descarte no puede ser un patrón en una expresión is ni una instrucción switch. En esos casos, para buscar coincidencias con cualquier expresión, use un patrón var con un patrón de descarte: var _. Un patrón de descarte puede ser un patrón en una expresión switch.

Para obtener más información, vea la sección Patrón de descarte de la nota de propuesta de características.

Patrón entre paréntesis

Puede colocar paréntesis alrededor de cualquier patrón. Normalmente, esto se hace para resaltar o cambiar la prioridad en patrones lógicos, como se muestra en el ejemplo siguiente:

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

Patrones de lista

Puede hacer coincidir una matriz o una lista con una secuencia de patrones, como se muestra en el ejemplo siguiente:

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 se muestra en el ejemplo anterior, un patrón de lista coincide cuando cada patrón anidado coincide con el elemento correspondiente de una secuencia de entrada. Puede usar cualquier patrón dentro de un patrón de lista. Para que coincida con cualquier elemento, use el patrón de descarte o, si también desea capturar el elemento, use el patrón var, como se muestra en el ejemplo siguiente:

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.

Los ejemplos anteriores buscan coincidencias de una secuencia de entrada completa con un patrón de lista. Para buscar coincidencias con los elementos solo al principio o al final de una secuencia de entrada, use el patrón de sector.., como se muestra en el ejemplo siguiente:

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

Un patrón de segmento busca coincidencias con cero o más elementos. Puede usar como máximo un patrón de segmento en un patrón de lista. El patrón de sector solo puede aparecer en un patrón de lista.

También puede anidar un subpatrón dentro de un patrón de segmento, como se muestra en el ejemplo siguiente:

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 más información, consulte la nota de propuesta de características para patrones de lista.

Especificación del lenguaje C#

Para más información, consulte la sección Patrones y coincidencia de patrones de la especificación del lenguaje C#.

Para obtener información sobre las características agregadas en C# 9 y versiones posteriores, consulte las siguientes notas de propuesta de características:

Consulte también