MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Noutăți în C# 12

Expresii de colecții

În C# 12, a fost simplificat modul de creare a array-urilor și colecțiilor prin intermediul expresiilor de colecții (collection expression), care oferă o abordare unificată pentru crearea colecțiilor. Astfel, dacă anterior crearea array-urilor arăta astfel:

int[] nums1 = { 1, 2, 3, 4 };
int[] nums2 = new int[] { };   // array gol

Acum poți scrie astfel:

int[] nums1 = [ 1, 2, 3, 4 ];
int[] nums2 = [];   // array gol

În mod similar, poți folosi expresii de colecții pentru a crea alte tipuri de colecții:

List<int> list1 = [1, 2, 3, 4];
List<int> list2 = []; // listă goală
Span<int> span1 = [1, 2, 3, 4];

Constructori primari

Constructorii primari (Primary constructors) permit adăugarea de parametri la definirea clasei/structurii și utilizarea acestor parametri în interiorul clasei/structurii:

var tom = new Person("Tom", 38);
Console.WriteLine(tom);

public class Person(string name, int age)
{
   public Person(string name) : this(name, 18) { }
   public string Name => name;
   public int Age => age;

   public override string ToString() => $"name: {name}, age: {age}";
}

Aici, pentru clasa Person este definit un constructor primar cu doi parametri - name și age. Acești parametri sunt folosiți pentru a inițializa proprietățile Name și Age și sunt utilizați în metoda ToString().

În fundal, pentru fiecare parametru al constructorului primar, în clasă se creează un câmp privat care stochează valoarea parametrului. Datorită acestui fapt, acești parametri pot fi utilizați în corpul clasei.

Pe lângă constructorii primari, clasa poate defini constructori suplimentari, așa cum este exemplificat mai sus. Însă acești constructori suplimentari trebuie să apeleze constructorul primar:

public Person(string name) : this(name, 18) { }

Pseudonime pentru tipuri

C# 12 permite definirea de pseudonime pentru orice tipuri. De exemplu:

using People = System.Collections.Generic.List<Person>;

People people = new() { new ("Tom", 38), new ("Bob", 42) };
people.ForEach(Console.WriteLine);

public record Person(string Name, int Age);

Aici, "People" servește ca pseudonim pentru tipul List<Person>.

Un alt exemplu:

using user = (string, int);
user tom = ("Tom", 38);
Console.WriteLine(tom);     // (Tom, 38)

Aici, numele user servește ca pseudonim pentru un tuplu de tip (string, int).

Mai mult, putem da nume elementelor tuplului:

using user = (string name, int age);
user tom = ("Tom", 38);
Console.WriteLine(tom.name);     // Tom
Console.WriteLine(tom.age);      // 38

Încă un exemplu:

using BinaryOp = System.Func<int, int, int>;

BinaryOp sum = (a, b) => a + b;
BinaryOp subtract = (a, b) => a - b;

DoOperation(10, 6, sum);        // 16
DoOperation(10, 6, subtract);   // 4

void DoOperation(int a, int b, BinaryOp op)
{
   Console.WriteLine(op(a, b));
}

Aici, delegatul de tip System.Func<int, int, int> primește pseudonimul BinaryOp.

Valori implicite pentru parametrii expresiilor lambda

Începând cu C# 12, parametrii expresiilor lambda pot avea valori implicite:


var welcome = (string message = "hello") => Console.WriteLine(message);

welcome("hello world"); // hello world
welcome();              // hello

Parametri ref doar pentru citire

Pentru a garanta că un parametru ref nu își va schimba valoarea, începând cu versiunea C# 12, se pot aplica parametri ref doar pentru citire. Acești parametri sunt precedați de cuvântul cheie readonly:

void Increment(ref readonly int n)
{
   // n++; // nu este permis, altfel va apărea o eroare de compilare
   Console.WriteLine($"Numărul în metoda Increment: {n}");
}

int number = 5;
Increment(ref number);
Console.WriteLine($"Numărul după metoda Increment: {number}");

În acest caz, în metoda Increment, parametrul n este transmis prin referință și este disponibil doar pentru citire. Dacă se încearcă modificarea valorii sale, vom primi o eroare la compilare.

Simplificarea definirii tipurilor

Începând cu versiunea C# 12, dacă un tip - clasă/structură/interfață - are o definiție goală (nu conține câmpuri, proprietăți, metode), acoladele după numele tipului pot fi omise:

class Person;
struct User;
interface Human;
← Lecția anterioară