Le langage C# 4 est apparu en avril 2010 avec la sortie de Visual Studio 20120. Il est donc aujourd’hui très largement déployé car nous développons presque tous avec la version 2010 (voir même 2012 pour certains).
Cette nouvelle version apporte des évolutions très intéressantes. Intéressantes tout d’abord car elles permettent de gagner du temps (moins de code, meilleure lisibilité), de faciliter les conversions de types et surtout l’interopérabilité des languages (échanges d’objet entre C# et Python par exemple).
Je vous propose de parcourir dans cet article quelques nouveautés qu’il faut connaitre car elle sont utilisent au quotidien :
- La Contra-variance et la Co-variance,
- Les Types dynamiques avec la DLR,
- Les Arguments nommés et optionnels.
Contra-variance et Co-variance en C#
La contra-variance est un mécanisme qui permet de convertir un type large (ex: Forme) en un type plus précis (ex: Triangle).
A l’inverse, la co-variance est le mécanisme qui permet de convertir un type précis (ex: Chat) en un type plus générique (ex: Animal).
Ces deux mécanismes peuvent désormais être utilisés pour les interfaces génériques, de manière implicite.
La covariance existe déjà dans C# depuis la version 1.0. Le code ci-dessous est un exemple de co-variance en CSharp :
[csharp]
object string = "string";
[/csharp]
Utilisation de la co-variance
La co-variance s’utilise avec le mot clé out dans les interfaces génériques en CSharp.
L’exemple ci-dessous montre un exemple (avec Animal et Chat) :
[csharp]
// Déclaration d’une interface avec le mot clé out
// (pour autoriser la co-variance)
interface IHabitation<out T> {}
class Habitation<T> : IHabitation<T> {}
class Animal {}
// Chat hérite de Animal
class Chat: Animal {}
public void Main()
{
IHabitation<Chat> habitatDuChat = new Habitation<Chat>();
// conversion explicite
IHabitation<Animal> habitatDunAnimal = habitatDuChat;
}
[/csharp]
Grâce à ce mécanisme vous pourrez désormais convertir des listes en listes avec des types plus génériques.
Utilisation de la contra-variance
A l’inverse, nous avons donc la contra-variance : la conversion d’un type générique en un type plus spécifique.
Cette fois-ci, il faudra utiliser le mot clé in dans l’interface générique.
class Alimentation<T> : IAlimentation<T> { }
// nous reprenons l’exemple avec Chat et Animal
public void Main()
{
IAlimentation<Animal> alimentDunAnimal = new Alimentation<Animal>();
// conversion explicite
IAlimentation<Chat> alimentDuChat = alimentDunAnimal;
}
[/csharp]
Il est important de bien connaitre la différence entre les deux mécanismes.
Au quotidien, c’est bien la covariance qui est utilisée le plus souvent.
Types dynamiques et DLR
Une des grandes nouveautés est bien sûr le typage dynamique. Il a été introduit grâce à la DLR (Dynamic Language Runtime).
La DLR est une surcouche de la CLR (Common Language Runtime) et permet de faciliter l’interopérabilité entre les langages de .NET.
Cette DLR permet la prise en charge des langages non développés par Microsoft à l’origine (la CLR supportait uniquement C# et VB.NET), comme par exemple Python et IronRuby.
Cette DLR permet de faire le lien entre les classes fortement typées (langages CSharp et VB.NET) et les classes non typées comme en Python.
Il sera ainsi possible de faire des appels sur des objets dont le compilateur ne connait pas le type au moment de la compilation.
Le type sera déterminé au moment de l’exécution.
Les types dynamiques seront surtout utilisés pour les cas suivants :
- Pour manipuler des objets provenant de langages non fortement typés (par exemple : Python, Ruby),
- Pour accéder à des objets COM (le wrapper sera plus simple),
- Pour simplifier l’accès à des objets utilisés auparavant avec la réflexion,
- Pour manipuler des objets dont la structure change (ex: HTML DOM).
Les types dynamiques sont déclarés à l’aide du mot clé dynamic en CSharp.
[csharp]public class Livre
{
public string Titre { get; set; }
}
public class Collection
{
public string Titre { get; set; }
public List<Livre> Livres = new List<Livre>();
}
public void AfficheObjet(dynamic obj)
{
// on utilise la propriété Titre du type dynamique
Console.WriteLine("Objet: Type={0}, Titre = {1}", obj.GetType(), obj.Titre);
}
public void Main()
{
Livre livre = new Livre() { Titre = "Apprendre le CSharp" };
Collection collection = new Collection() { Titre = "Programmation" };
AfficheObjet(livre);
AfficheObjet(collection);
}
[/csharp]
Arguments nommés et optionnels
Habituellement, quand on écrit une méthode qui prend en charge une longue liste de paramètres, il est toujours difficile de s’y retrouver au moment de faire l’appel de cette méthode. Déjà avec 3 ou 4 paramètres, il peut arriver de mélanger l’ordre.
Imaginez si vous avez trois paramètres du type string. Comment faites-vous pour les distinguer et appeler la méthode en passant les paramètres dans le bon ordre ?
Pour résoudre ce problème, Microsoft a introduit les arguments nommés. Ils s’utilisent conjointement avec les arguments optionnels.
[csharp] public static void Log(string message,string category = "ALL", string level = "INFO") {}
public static void Main()
{
// Voici différents appels de la même méthode
// Dans certains cas, les valeurs par défaut sont utilisées
Log("message");
Log("message", category: "NETWORK");
Log("message", level: "ERROR");
Log("message", "NETWORK", "ERROR");
}
L’utilisation des paramètres nommés est surtout utile pour spécifier un argument optionnel. Mais elle permet aussi de passer des arguments dans n’importe quel ordre.
A vous d’essayer
Maintenant que vous avez vu les trois grandes nouveautés de la version 4 du langage, je vous invite à essayer vous aussi ces nouvelles syntaxes.
Elles permettent de gagner du temps au quotidien et d’améliorer votre efficacité.
Je vous proposerais, dans un prochain article, de détailler un peu l’usage des types dynamiques. Ils permettent de mettre en place des mécanismes très intéressants comme les Objet Proxy par exemple.