MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Verificarea existenței și obținerea elementelor

Un set de metode în LINQ permite verificarea existenței elementelor într-o colecție și obținerea acestora.

Metoda All

Metoda All() verifică dacă toate elementele îndeplinesc o anumită condiție. Dacă toate elementele îndeplinesc condiția, se returnează true. De exemplu:

string[] people = { "Tom", "Tim", "Bob", "Sam" };

// verificăm dacă toate elementele au lungimea de 3 caractere
bool allHas3Chars = people.All(s => s.Length == 3); // true
Console.WriteLine(allHas3Chars);

// verificăm dacă toate șirurile încep cu litera T
bool allStartsWithT = people.All(s => s.StartsWith("T")); // false
Console.WriteLine(allStartsWithT);

În primul caz, verificăm dacă toate șirurile din array-ul people au lungimea de trei caractere. Deoarece această condiție este adevărată, metoda All returnează true. În al doilea caz, verificăm dacă toate șirurile încep cu litera "T". Această condiție este falsă, deci metoda All returnează false.

Metoda Any

Metoda Any() acționează într-un mod similar, dar returnează true dacă cel puțin un element din colecție îndeplinește o anumită condiție:

string[] people = { "Tom", "Tim", "Bob", "Sam" };
// verificăm dacă toate elementele au lungimea mai mare de 3 caractere
bool allHasMore3Chars = people.Any(s => s.Length > 3); // false
Console.WriteLine(allHasMore3Chars);

// verificăm dacă toate șirurile încep cu litera T
bool allStartsWithT = people.Any(s => s.StartsWith("T")); // true
Console.WriteLine(allStartsWithT);

Prima expresie va returna false, deoarece toate șirurile au lungimea de 3 caractere. A doua expresie va returna true, deoarece există șiruri în colecție care încep cu litera "T".

Metoda Contains

Metoda Contains() returnează true dacă colecția conține un anumit element.

string[] people = { "Tom", "Tim", "Bob", "Sam" };

// verificăm dacă există șirul "Tom"
bool hasTom = people.Contains("Tom"); // true
Console.WriteLine(hasTom);

// verificăm dacă există șirul "Mike"
bool hasMike = people.Contains("Mike"); // false
Console.WriteLine(hasMike);

Este important de menționat că pentru compararea obiectelor se folosește implementarea metodei Equals. Prin urmare, dacă lucrăm cu obiecte de tip propriu, trebuie să implementăm această metodă:

Person[] people = { new Person("Tom"), new Person("Sam"), new Person("Bob")};

var tom = new Person("Tom");
var mike = new Person("Mike");

// verificăm dacă există "Tom"
bool hasTom = people.Contains(tom); // true
Console.WriteLine(hasTom);

// verificăm dacă există "Mike"
bool hasMike = people.Contains(mike); // false
Console.WriteLine(hasMike);

class Person
{
   public string Name { get; }
   public Person(string name) => Name = name;

   public override bool Equals(object? obj)
   {
       if (obj is Person person) return Name == person.Name;
       return false;
   }

   public override int GetHashCode() => Name.GetHashCode();
}

Totuși, Contains nu întotdeauna returnează datele așteptate. De exemplu:

string[] people = { "tom", "Tim", "bOb", "Sam" };

// verificăm dacă există șirul "Tom"
bool hasTom = people.Contains("Tom"); // false
Console.WriteLine(hasTom);

// verificăm dacă există șirul "Bob"
bool hasBob = people.Contains("Bob"); // false
Console.WriteLine(hasBob);

În acest caz, în array nu există șirul "Tom", dar există șirul "tom". Prin urmare, apelul people.Contains("Tom") va returna false. Pentru a evita acest comportament nedorit, putem seta logica de comparare folosind implementarea interfeței IComparer și apoi să o transmitem ca al doilea parametru în metoda Contains:

using System.Diagnostics.CodeAnalysis;

string[] people = { "tom", "Tim", "bOb", "Sam" };

// verificăm dacă există șirul "Tom"
bool hasTom = people.Contains("Tom", new CustomStringComparer()); // true
Console.WriteLine(hasTom);

// verificăm dacă există șirul "Bob"
bool hasBob = people.Contains("Bob", new CustomStringComparer()); // true
Console.WriteLine(hasBob);

class CustomStringComparer : IEqualityComparer<string>
{
   public bool Equals(string? x, string? y)
   {
       if (x is null || y is null) return false;
       return x.ToLower() == y.ToLower();
   }

   public int GetHashCode([DisallowNull] string obj) => obj.ToLower().GetHashCode();
}

Interfața IEqualityComparer este tipizată cu tipul datelor comparate (în acest caz, tipul String). Pentru implementarea acestei interfețe, trebuie să definim metodele Equals și GetHashCode. În metoda Equals, comparăm șirurile în litere mici, iar în metoda GetHashCode returnăm codul hash al șirului în litere mici.

Metodele First/FirstOrDefault

Metoda First() returnează primul element al secvenței:

string[] people = { "Tom", "Bob", "Tim", "Sam" };

// primul element
var first = people.First(); // Tom
Console.WriteLine(first);

De asemenea, metoda First poate accepta o metodă care reprezintă condiția. În acest caz, metoda returnează primul element care corespunde condiției:

string[] people = { "Tom", "Bob", "Kate", "Tim", "Mike", "Sam" };

// primul șir, a cărui lungime este de 4 caractere
var firstWith4Chars = people.First(s => s.Length == 4); // Kate
Console.WriteLine(firstWith4Chars);

Aici selectăm primul element, a cărui lungime este de 4 caractere.

Trebuie să ținem cont că, dacă colecția este goală sau nu există elemente care să îndeplinească condiția, se va genera o excepție.

string[] people = { "Tom", "Bob", "Kate", "Tim", "Mike", "Sam" };

// primul șir, a cărui lungime este de 5 caractere
var firstWith5Chars = people.First(s => s.Length == 5); // ! excepție
Console.WriteLine(firstWith5Chars);

var first = new string[] {}.First(); // ! excepție
Console.WriteLine(first);

Metoda FirstOrDefault() returnează de asemenea primul element și poate accepta o condiție, doar că, dacă colecția este goală sau nu există elemente care să îndeplinească condiția, metoda returnează valoarea implicită:

string[] people = { "Tom", "Bob", "Kate", "Tim", "Mike", "Sam" };

// primul element
var first = people.FirstOrDefault(); // Tom
Console.WriteLine(first);

// primul șir, a cărui lungime este de 4 caractere
var firstWith4Chars = people.FirstOrDefault(s => s.Length == 4); // Kate
Console.WriteLine(firstWith4Chars);

// primul element dintr-o colecție goală
var firstOrDefault = new string[] {}.FirstOrDefault();
Console.WriteLine(firstOrDefault); // null

Trebuie să ținem cont că pentru colecțiile de tipuri de referință, FirstOrDefault returnează o valoare de tip T? (în exemplul de mai sus - string?), adică o valoare care poate fi null, iar valoarea implicită este null. Pentru colecțiile de tipuri numerice, se returnează direct valoarea de tip T, iar valoarea implicită este 0.

Putem seta valoarea implicită, transmițând-o ca unul dintre argumente:

string[] people = { "Tom", "Bob", "Kate", "Tim", "Mike", "Sam" };

string? firstWith5Chars = people.FirstOrDefault(s => s.Length == 5, "Undefined");
Console.WriteLine(firstWith5Chars); // Undefined

// primul element dintr-o colecție goală de șiruri
string? firstOrDefault = new string[] {}.First

OrDefault("hello"); // hello - valoare implicită
Console.WriteLine(firstOrDefault); // hello

// primul element dintr-o colecție goală de int
int firstNumber = new int[] {}.FirstOrDefault(100); // 100 - valoare implicită
Console.WriteLine(firstNumber); // 100

Metodele Last și LastOrDefault

Metoda Last() este similară metodei First, doar că returnează ultimul element. Dacă colecția nu conține elemente care să îndeplinească condiția sau este goală, metoda generează o excepție.

string[] people = { "Tom", "Bob", "Kate", "Tim", "Mike", "Sam" };

string last = people.Last();
Console.WriteLine(last); // Sam

string lastWith4Chars = people.Last(s => s.Length == 4);
Console.WriteLine(lastWith4Chars); // Mike

Metoda LastOrDefault() returnează ultimul element sau valoarea implicită dacă colecția nu conține elemente care să îndeplinească condiția sau este goală:

string[] people = { "Tom", "Bob", "Kate", "Tim", "Mike", "Sam" };

string? last = people.LastOrDefault();
Console.WriteLine(last); // Sam

string? lastWith4Chars = people.LastOrDefault(s => s.Length == 4);
Console.WriteLine(lastWith4Chars); // Mike

string? lastWith5Chars = people.LastOrDefault(s => s.Length == 5);
Console.WriteLine(lastWith5Chars); // null

string? lastWith5CharsOrDefault = people.LastOrDefault(s => s.Length == 5, "Undefined");
Console.WriteLine(lastWith5CharsOrDefault); // Undefined

// primul element dintr-o colecție goală de șiruri
string? lastOrDefault = new string[] {}.LastOrDefault("hello");
Console.WriteLine(lastOrDefault); // hello

Aceste metode oferă flexibilitatea de a verifica existența și obține elementele din colecții, fie că sunt simple sau complexe, asigurând astfel un control eficient asupra datelor.

← Lecția anterioară Lecția următoare →