Accueil

Les nouveautés de C# 6

by Jean-Camille Mercier 20. août 2015 10:20

Visual studio 2015 est disponible depuis quelques semaines, c'est l'occasion de découvrir les nouveautés du langage C#6. Voici déjà en préambule l'historique des version de C# :

  • C# est apparu en 2001 avec Visual Studio.Net 
  • v2 en 2005 avec les classes partielles, les nullables, les méthodes anonymes et les générics
  • v3 en 2007 avec Linq, les var, les méthodes d'extension, les expressions lambda
  • v4 en 2010 avec les arguments nommés, les dynamics, la programmation parallèle
  • v5 en 2012 avec async / await, le [CallerMemberName]
Pour cette nouvelle mouture, nous avons de le droits à des tips vraiment sympa :
 
1 - Le mot clef nameof
On l'attendait depuis l'utilisation massive de NotifyPropertyChanged dont l'utilisation du nom de le propriété en string posait problème de puis longtemps (voir cet article). Nous avons maintenant un mot clef qui permet de récupérer le nom d'un symbole de manière générale. Ca fonctionne donc pour une propriété, un champ, une variable ou même une méthode.
nameof(objet.MaProp) -> "MaProp"
nameof(objet.MaFonc) -> "MaFonc"
 
2 - La vérification de nullité avec ?.
Voici maintenant un nouvel opérateur ! Le "?." évite les nullReferenceException en incluant un test de nullité à notre place. Si l'objet que l'on accède est null, alors la valeur renvoyé sera null aussi.
Person obj = null;
int? age = obj?.Age;

// Est la même chose que : 

if (obj != null)
   age = obj.Age;
Ce qui est intéressant c'est que l'on peut enchainer les "?." pour éviter les tests à rallonge !
int? cp = person?.Mere?.Ville?.CodePostal
Et si l'on veut donner une valeur par défaut, il suffit de l'associer avec un double point d'interrogation
int age = peson?.Age ? ? 18;
 
3 - Le nouveau système de string.format
Des formattage de chaine de caractère on en fait énormément, avec ce nouveau système, C# nous aide à obtenir un code plus lisible en utilisant les variables directement dans la chaine. Pour ce faire, on doit préfixer la chaine par "$" et l'on utilise les variable à place des numéros toujours entre "{}"
string c = $"Bonjour M.{person.Nom}, il est {DateTime.Now.Hour:T}";
 
4 - L'enrichissement des lambda
Ce n'est pas vraiment une lambda, mais ça se rapproche d'une méthode anonyme, voici une manière plus concise d'écrire une propriété ou un méthode qui ne possède qu'une seule instruction "return"
public int NbFreres
{
    get { return this.Freres.Count(); }
}

// Devient : 

public int NbFreres => this.Freres.Count();

// Ou

public int GetNbFreres() => this.Freres.Count();
 
5 - Une nouvelle méthode d'initialisateur de dictionary et des getters
Initialiser un dictionary n'est pas très intuitif, là encore C#6 nous aide à obtenir un code plus lisible : 
var surnoms = new Dictionary<string, Person>
{
    { "Toto", new Person("Tom") },
    { "Papy", new Person("Jean") },
    ...
};

// Devient :

var surnoms = new Dictionary<string, Person>
{
    ["Toto"] = new Person("Tom"),
    ["Papy"] = new Person("Jean"),
    ...
};
Et un peu dans le même esprit, il est maintenant possible d'initialiser les getters court :
int Age {get; set; } = 18;
 
6 - Enrichissement du catch 
La limitation qui empêchait d'écrire un await dans un bloc catch ou finally est maintenant levée ! 
private async Task DoSomethingAsync()
{
    try
    {
        // Some async code that can throw an exception
        ...
    }
    catch (Exception ex)
    {
        var dialog = new MessageDialog("Something went wrong!");
        await dialog.ShowAsync();
    }
}
De plus, il est possible de poser des conditions sur les blocs catch pour tester un code d'erreur par exemple :
try
{
   ...
}
catch(IOException ex) if (ex.HResult == 0x80070020)
{
    // File is in use by another process
}
catch(IOException ex) if (ex.HResult == 0x80070035)
{
    // Network path was not found
}
catch(Exception ex)
{
    // Something else happened
}
 
7 - Using de namespace dans une portée
Les using sont normalement définit en tête de fichier pour tout le fichier. Mais il peut arriver que l'on souhaite utiliser un using que dans une partie de son code, pour éviter les conflits de nommage par exemple. C'est maintenant possible avec une syntaxe un peu particulière. On peut aussi préciser un objet static que l'on utilise fréquement.
public void MaFonction()
{
   // Using dans la portée
   using static Inetsis.Helpers;

   ...
   // Utilisation directe d'un objet static
   using static System.Math;
   double distance = Sqrt(x * x + y * y);
}
 
A noter que toutes ces évolutions sont utilisables avec le framework 4;