Patrones lógicos
A partir de C# 9.0, utiliza los combinadores de patrones not, and y or para crear los siguientes patrones lógicos:
- Negación que coincide con una expresión cuando el patrón negado no coincide con la expresión. El siguiente ejemplo muestra cómo puede negar un patrón nulo constante para verificar si una expresión no es nula:
if (input is not null)
{
// ...
}
- Conjuntiva (and) que coincide con una expresión cuando ambos patrones coinciden con la expresión. El siguiente ejemplo muestra cómo puede combinar patrones relacionales para verificar si un valor está en un cierto rango:
Console.WriteLine(Classify(13)); // output: HighConsole.WriteLine(Classify(-100)); // output: Too lowConsole.WriteLine(Classify(5.7)); // output: Acceptablestatic 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",};
- Disyuntiva (or) que coincide con una expresión cuando cualquiera de los patrones coincide con la expresión, como muestra el siguiente ejemplo:
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 muestra el ejemplo anterior, puede utilizar repetidamente los combinadores de patrones en un patrón.
Precedencia y orden de verificación
La siguiente lista ordena los combinadores de patrones comenzando desde la precedencia más alta hasta la más baja:
- not
- and
- or
Para especificar explícitamente la precedencia, podemos usar paréntesis, como muestra el siguiente ejemplo:
static bool IsLetter(char c) => c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z');
Patrón de propiedad
Se utiliza un patrón de propiedad para hacer coincidir las propiedades o campos de una expresión con patrones anidados, como muestra el siguiente ejemplo:
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 una expresión no es nulo y cada patrón anidado coincide con la propiedad o el campo correspondiente del resultado de la expresión.
También puede agregar una verificación de tipo en tiempo de ejecución y una declaración de variable a un patrón de propiedad, como muestra el siguiente ejemplo:
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."),
};
Un patrón de propiedad es un patrón recursivo. Es decir, puede utilizar cualquier patrón como patrón anidado. Se puede utilizar un patrón de propiedad para hacer coincidir partes de datos con patrones anidados, como muestra el siguiente ejemplo:
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 } };
El ejemplo anterior usa dos funciones disponibles en C# 9.0 y versiones posteriores: o combinador de patrones y tipos de registro.
A partir de C# 10, puede hacer referencia a propiedades o campos anidados dentro de un patrón de propiedad. Esta capacidad se conoce como patrón de propiedad extendida. Por ejemplo, puede refactorizar el método del ejemplo anterior en el siguiente código equivalente:
static bool IsAnyEndOnXAxis(Segment segment) =>
segment is { Start.Y: 0 } or { End.Y: 0 };