Pattern-uri de liste
Pattern-urile de liste permit potrivirea expresiilor cu liste și array-uri. Acest pattern este disponibil începând cu versiunea C# 11.
Potrivire completă cu un array/listă:
Console.WriteLine(GetNumber(new[] { 1, 2, 3, 4, 5 })); // 1
Console.WriteLine(GetNumber(new[] { 1, 2})); // 3
Console.WriteLine(GetNumber(new int[] {})); // 4
Console.WriteLine(GetNumber(new[] { 1, 2, 5 })); // 5
int GetNumber(int[] values) => values switch
{
[1, 2, 3, 4, 5] => 1,
[1, 2, 3] => 2,
[1, 2] => 3,
[] => 4,
_ => 5
};
În mod similar, în loc de array-uri se pot folosi liste:
List<int> numbers = new List<int> { 1, 2, 3 };
Console.WriteLine(GetNumber(numbers)); // 2
int GetNumber(List<int> values) => values switch
{
[1, 2, 3, 4, 5] => 1,
[1, 2, 3] => 2,
[1, 2] => 3,
[] => 4,
_ => 5
};
De asemenea, pattern-urile de liste pot fi folosite în construcția if:
int[] numbers = { 1, 2, 3, 4, 5 };
if (numbers is [1, 2, 3, 4, 5])
{
Console.WriteLine("[1, 2, 3, 4, 5]");
}
Substituția _
Cu ajutorul pattern-ului _ se poate desemna un element unic care are orice valoare. De exemplu, pattern-ul [2, _, 5] corespunde oricărui array de trei elemente în care între 2 și 5 se află o valoare arbitrară. Iar array-ul [_, _] corespunde oricărui array de două elemente arbitrare.
Câteva exemple:
Console.WriteLine(GetNumber(new[] { 2, 3, 5 })); // 1
Console.WriteLine(GetNumber(new[] { 2, 4, 6 })); // 2
Console.WriteLine(GetNumber(new[] { 1, 2, 5 })); // 3
Console.WriteLine(GetNumber(new[] { 1, 2, 3 })); // 4
Console.WriteLine(GetNumber(new int[] { })); // 5
int GetNumber(int[] values) => values switch
{
[2, _, 5] => 1,
[2, _, _] => 2,
[_, _, 5] => 3,
[_, _, _] => 4,
_ => 5
};
Pattern-ul slice
Pentru a transmite un număr arbitrar de elemente din array/listă, se folosește pattern-ul slice ... De exemplu, pattern-ul [1, 2, .., 5] corespunde unui array care începe cu 1, urmat de 2, iar ultimul element din array este 5. Între 2 și 5 poate exista orice număr de valori întregi. Adică, pattern-ul [1, 2, .., 5] va corespunde unor array-uri precum:
int[] arr1 = { 1, 2, 3, 4, 5 };
int[] arr2 = { 1, 2, 5 };
int[] arr3 = { 1, 2, 66, 77, 88, 5 };
Cu ajutorul pattern-ului .. se poate desemna un număr arbitrar de elemente atât la început, cât și la sfârșitul array-ului/listei. De exemplu, pattern-ul [2, ..] reprezintă un array care începe cu 2. Iar pattern-ul [.., 5] reprezintă un array care se termină cu elementul 5. Pattern-ul [..] reprezintă un array care conține un număr arbitrar de elemente. De exemplu:
Console.WriteLine(GetNumber(new[] { 2, 5 })); // 1
Console.WriteLine(GetNumber(new[] { 2, 3, 4, 5 })); // 1
Console.WriteLine(GetNumber(new[] { 2 })); // 2
Console.WriteLine(GetNumber(new[] { 2, 3, 4 })); // 2
Console.WriteLine(GetNumber(new[] { 3, 4, 5 })); // 3
Console.WriteLine(GetNumber(new[] { 5 })); // 3
Console.WriteLine(GetNumber(new int[] { })); // 4
Console.WriteLine(GetNumber(new[] { 1 })); // 4
Console.WriteLine(GetNumber(new[] { 1, 2, 3 })); // 4
int GetNumber(int[] values) => values switch
{
[2, .., 5] => 1, // dacă primul element este 2, iar ultimul este 5
[2, ..] => 2, // dacă primul element este 2
[.., 5] => 3, // dacă ultimul element este 5
[..] => 4 // număr arbitrar de elemente
};
Pattern-ul slice poate fi combinat cu simboluri de substituție _, de exemplu:
int GetNumber(int[] values) => values switch
{
[_, .., _] => 1,
[..] => 2
};
În acest caz, pattern-ul [_, .., _] presupune un array format din cel puțin două elemente arbitrare, iar între primul și ultimul element poate exista un număr arbitrar de alte elemente:
Console.WriteLine(GetNumber(new[] { 1, 2, 3, 4 })); // 1
Console.WriteLine(GetNumber(new[] { 1, 2, 3 })); // 1
Console.WriteLine(GetNumber(new[] { 1, 2 })); // 1
Console.WriteLine(GetNumber(new[] { 1 })); // 2
Console.WriteLine(GetNumber(new int[] { })); // 2
int GetNumber(int[] values) => values switch
{
[_, .., _] => 1,
[..] => 2
};
Obținerea elementelor în variabile
Valorile individuale din array/listă pot fi obținute în variabile, de exemplu:
int[] numbers = { 2, 3, 5 };
if (numbers is [var first, var second, .., var last])
{
Console.WriteLine($"first: {first}, second: {second} last: {last}");
}
În acest caz, obținem primul element al array-ului în variabila first, al doilea element în variabila second, iar ultimul element în variabila last.
Exemplu cu diferite array-uri:
Console.WriteLine(GetData(new[] { 1, 2, 3 })); // First: 1 Second: 2 Last: 3
Console.WriteLine(GetData(new[] { 2, 4, 6, 8 })); // First: 2 Second: 4 Last: 8
Console.WriteLine(GetData(new[] { 1, 2 })); // Array has less than 3 elements
string GetData(int[] values) => values switch
{
[var first, var second, .., var last] => $"First: {first} Second: {second} Last: {last}",
[..] => "Array has less than 3 elements"
};
În acest caz, obținem primul element al array-ului în variabila first, al doilea element în variabila second, iar ultimul element în variabila last.
În același timp, valorile proiectate pe pattern-ul .. pot fi, de asemenea, obținute într-o variabilă. De exemplu, în pattern-ul [2, .. var middle, 5] elementele proiectate pe .. pot fi transmise în variabila middle. Câteva exemple:
Console.WriteLine(GetSlice(new[] { 2, 3, 4, 5 })); // Middle: 3, 4
Console.WriteLine(GetSlice(new[] { 2, 4, 6, 8 })); // End: 4, 6, 8
Console.WriteLine(GetSlice(new[] {
1, 2, 3, 5 })); // Start: 1, 2, 3
Console.WriteLine(GetSlice(new[] { 1, 2, 3, 4 })); // All: 1, 2, 3, 4
Console.WriteLine(GetSlice(new int[] { })); // All:
string GetSlice(int[] values) => values switch
{
[2, .. var middle, 5] => $"Middle: {string.Join(", ", middle)}",
[2, .. var end] => $"End: {string.Join(", ", end)}",
[.. var start, 5] => $"Start: {string.Join(", ", start)}",
[.. var all] => $"All: {string.Join(", ", all)}"
};
Proprietăți ale colecțiilor
Este de menționat că, deoarece array-urile și listele sunt clase C# obișnuite care au proprietăți, putem aplica pentru ele și pattern-ul de proprietăți. Combinarea pattern-ului de proprietăți și pattern-ului de liste permite simplificarea rezolvării unor sarcini.
De exemplu, avem o sarcină: dacă array-ul are trei elemente, să îl descompunem în trei variabile:
int[] numbers = { 2, 3, 5 };
if (numbers is { Length: 3 } and [var first, var second, var third])
{
Console.WriteLine($"first: {first}, second: {second} third: {third}");
}