Nouveautés de C# 7.2

C# 7.2 vient de sortir, voici les nouveautés dont vous pouvez dès à présent profiter. Commençons par les modifications anecdotiques au niveau framework, mais toutefois fort pratiques

private protected

Nous avons droit à un nouveau modificateur. Nous possédions les classiques public, private et protected de la POO auquel s’ajoutait internal pour donner une visibilité au sein de l’assembly et l’hybride protected internal qui donnait une visibilité totales au sein de l’assembly ainsi qu’un accès à partir des classes dérivées.

Nous avons désormais private protected qui rend un membre visible pour sa classe et les classes dérivées au sein du même assembly.

class Vehicle
{
private protected string Name
{
get;
set;
}
}

class Car : Vehicle
{
void DisplayName()
{
Name = "Toto"; // OK, le membre est accessible, Car hérite de Vehicle
Vehicle v = new Vehicle();
v.Name = "titi"; //Impossible, le membre est privé
}
}

Notez dans l’exemple ci-dessus, si la classe Car se trouve dans un assembly différent de Vehicule, alors l’appel Name = « Toto » devient également impossible (le private protected n’autorise le protected que dans le même assembly).

 

Trait de soulignement de début dans les littéraux numériques

A l’image de Java, il était possible en C# 7 d’utiliser l’underscore dans les valeurs littérales comme dans l’exemple suivant :

int binValue1 = 0b0100_0101;

Sauf qu’il n’était pas possible d’utiliser l’underscore en début de littéral. Avec C# 7.2 c’est désormais résolu. On peut ainsi écrire

int binValue2 = 0b_0100_0101;

Les arguments nommés peuvent être suivis d’arguments de position

Je reformule, car dit ainsi, on peut ne pas comprendre. Imaginons la méthode suivante :

void FaitUnTrucDeDingue(string nom, int nombre, decimal montant, int ageDuCapitaine)
{
// Un truc de ouf
}

Nous sommes ici obligés de passer 4 paramètres. Comme vous le savez probablement, les arguments facultatifs doivent être placés à la fin.

void FaitUnTrucDeDingue(string nom="toto", int nombre, decimal montant, int ageDuCapitaine) // Ne compile pas

void FaitUnTrucDeDingue( int nombre, decimal montant, int ageDuCapitaine, string nom = "toto")// Compile

Prenons la dernière méthode ci-dessous qui compile. Vous savez probablement également que l’on peut utiliser des arguments nommés pour appeler une fonction. C#7.2 permet de nommés des arguments et les faire suivre par des arguments de position.

FaitUnTrucDeDingue(nombre: 4, ageDuCapitaine:35, montant:6); // Compile en C# 7.2 et C# 7.1
FaitUnTrucDeDingue(4, 6, ageDuCapitaine: 35); // Compile en C# 7.2 et C# 7.1 FaitUnTrucDeDingue(nombre: 4, 6, 35); // Compile en C# 7.2 pas en C# 7.1

Outre ces modifications, le C# 7.2 se focalise surtout sur les types valeurs. Il offre une possibilité d’usage à l’image des types références (même sémantique). L’objectif est d’améliorer les performances en réduisant les copies de type valeur tout en ne nécessitant pas les allocations mémoires liées au type référence. Voici les améliorations en quelques lignes.
Imaginons la structure suivante

public struct MyCoordinate
{
int X { get; set; }
int Y { get; set; }
}

Prenons maintenant la méthode suivante

public double GetLength(MyCoordinate a, MyCoordinate b)
{
return Math.Sqrt(Math.Pow(b.X - a.X, 2) + Math.Pow(b.Y - a.Y, 2));
}

L’appel de cette méthode implique des recopies sur la pile puisque nous utilisons une structure.

 Mot clé  in

Mis en paramètre d’une méthode, il permet de spécifier qu’un argument est passé par référence mais n’est pas modifié par la méthode appelée.

public double GetLength(in MyCoordinate a,in MyCoordinate b)
{
return Math.Sqrt(Math.Pow(b.X - a.X, 2) + Math.Pow(b.Y - a.Y, 2));
}

L’appelant n’a rien à changer à son code mais l’appel est ici optimisé

ref readonly

Utilisé sur les retours de méthode pour indiquer qu’une méthode retourne une valeur par référence mais n’autorise pas les écritures sur cet objet.

readonly struct

Cette déclaration permet d’indiquer qu’une structure est immuable. Ne bougeant pas, elle doit être passé comme un paramètre in aux méthodes de ses membres.

Voici un exemple d’implémentation :

readonly public struct MyCoordinate
{
public MyCoordinate(double x, double y)
{
X = x;
Y = y;
}
public double X { get; } //set interdit, nous sommes en readonly
public double Y { get; } //set interdit, nous sommes en readonly

private static readonly MyCoordinate origin = new MyCoordinate();
public static ref readonly MyCoordinate Origin => ref origin;
}

 

   ref struct

Ainsi déclaré, la structure est forcée à être instancié sur le tas. Cette fonctionnalité est surtout utile pour Span<T>