Vous êtes sur la page 1sur 19

Les nouveauts du langage C# 3.

0
Version 1.4

James RAVAILLE
http://blogs.dotnet-france.com/jamesr

Les nouveauts du langage C# 3.0

Sommaire

Introduction ..................................................................................................................................... 3 1.1 1.2 Prsentation ............................................................................................................................ 3 Pr-requis ................................................................................................................................ 3

Les accesseurs simplifis ................................................................................................................. 4 2.1 2.2 Prsentation ............................................................................................................................ 4 Exemple de mise en uvre ..................................................................................................... 4

Les mthodes partielles................................................................................................................... 6 3.1 3.2 Prsentation ............................................................................................................................ 6 Exemple de mise en uvre ..................................................................................................... 7

Les initialiseurs dobjets et de collections ....................................................................................... 9 4.1 4.2 Prsentation ............................................................................................................................ 9 Exemple de mise en uvre ..................................................................................................... 9 Les initialiseurs dobjets .................................................................................................. 9 Les initialiseurs de collections ....................................................................................... 10

4.2.1 4.2.2 5

Linfrence de type et les types anonymes ................................................................................... 11 5.1 5.2 5.3 Prsentation de linfrence de type ...................................................................................... 11 Prsentation des types anonymes ........................................................................................ 11 Exemple de mise en uvre ................................................................................................... 11

Les mthodes dextension ............................................................................................................. 13 6.1 6.2 6.3 Prsentation .......................................................................................................................... 13 Exemple de mise en uvre ................................................................................................... 14 Rgles particulires ............................................................................................................... 15

Les expressions lambda ................................................................................................................. 17 7.1 7.2 7.3 Prsentation .......................................................................................................................... 17 Exemple de mise en uvre ................................................................................................... 17 Utilisation des expressions lambda comme paramtre de mthode ................................... 18

Conclusion ..................................................................................................................................... 19

Dotnet France Association James RAVAILLE

Les nouveauts du langage C# 3.0

1 Introduction
1.1 Prsentation
En Fvrier 2008, Microsoft sort officiellement et pour le grand public, Visual Studio 2008, la version 3.5 du Framework .NET, ainsi quune nouvelle version du langage C#. Nous vous proposons dans ce cours, de vous prsenter chacune des nouveauts de ce langage, avec pour chacune dentre elles : Une partie thorique afin de vous expliquer en quoi elle consiste, et quel est son but, dans quels cas il est ncessaire/conseill de lutiliser Une partie pratique avec des exemples de mise en uvre.

Ces nouveauts sont les suivantes : Les accesseurs simplifis. Les mthodes partielles. Les initialiseurs dobjets et de collections. Linfrence de type. Les types anonymes. Les mthodes dextension. Les expressions lambda.

1.2 Pr-requis
Avant de lire ce cours, vous devez avoir lu les prcdents cours sur le langage C# : Le langage C#. La programmation oriente objet avec le langage C#. Les nouveauts du langage C# 2.0.

Dotnet France Association James RAVAILLE

Les nouveauts du langage C# 3.0

2 Les accesseurs simplifis


2.1 Prsentation
Les accesseurs (ou proprits) simplifis, offrent la possibilit de dfinir, au sein dune classe, des proprits sans implmenter les attributs quils grent , ni le corps de laccesseur en lecture (getter) et laccesseur en criture (setter). En effet, en rtro-compilant le code obtenu, on peut observer que lattribut gr est gnr automatiquement, tout comme le code des accesseurs. Quelques restrictions toutefois, par rapport aux accesseurs cris avec le langage C# 2.0 : Les accesseurs en lecture et en criture, doivent obligatoirement tre tous les deux prsents. Il nest pas possible de dfinir un accesseur en lecture ou criture seule. Les accesseurs en lecture et en criture ont le mme niveau de visibilit : impossible de rduire le niveau de visibilit de laccesseur, en lecture ou en criture. Le type de lattribut gnr est obligatoirement celui de laccesseur. Lintrt des accesseurs simplifis est dcrire moins de code dans les classes.

2.2 Exemple de mise en uvre


Soit la classe Voiture suivante :
// C# public class Voiture { #region Attributs et accesseurs private string _NumeroImmatriculation; public string NumeroImmatriculation { get { return this._NumeroImmatriculation; } set { this._NumeroImmatriculation = value; } } public string Marque { get; set; } #endregion }

La classe ci-dessus prsente : Un attribut avec son accesseur (aussi appel accesseur par dfaut ), contenant le numro dimmatriculation dune voiture. Un autre accesseur avec une forme particulire, contenant la marque dune voiture : les accesseurs en lecture et en criture ne sont pas implments. Il sagit dun accesseur simplifi. Au final, lors de la gnration du code MSIL, notre classe possde deux attributs, et pour chacun dentre eux, un accesseur. Pour lobserver, il suffit de rtro-compiler le code Dotnet France Association James RAVAILLE

Les nouveauts du langage C# 3.0 MSIL de cette classe, avec un outil tel que gate.com/products/reflector). Voici ce quon peut observer : Reflector (http://www.red-

public class Voiture { // Fields private string _NumeroImmatriculation; [CompilerGenerated]private string <Marque>k__BackingField; // Properties public string Marque { [CompilerGenerated] get; [CompilerGenerated] set; } public string NumeroImmatriculation { get; set; }

Dotnet France Association James RAVAILLE

Les nouveauts du langage C# 3.0

3 Les mthodes partielles


3.1 Prsentation
Les mthodes partielles sont obligatoirement contenues dans des classes partielles (nouveauts du langage C# 2.0), elles-mmes contenues dans le mme projet. Pour rappel, deux classes partielles constituent la mme classe, spares physiquement dans deux fichiers ou plus. Une mthode partielle est une mthode dont : La signature de la mthode est dfinie dans une classe partielle. Limplmentation de la mthode est dfinie dans une autre partie de la classe partielle. Cette implmentation est optionnelle.

Voici les caractristiques des mthodes partielles : Elles sont obligatoirement prives. Elles ne peuvent tre appeles que dans la classe dans laquelle elles sont dfinies. Aucun niveau de visibilit ne doit tre spcifi (une erreur de compilation survient, le cas chant). Elles sont dfinies avec le mot cl partial.

Lintrt majeur des classes partielles rside dans les gnrateurs de code, ou bien encore dans des projets qui partagent des assemblies communes :

Gnrateur de code Dveloppeur 1 Dveloppeur 2

ou
Classe partielle VoitureCourse Fichier VoitureCourse1.cs Classe VoitureCourse Classe partielle VoitureCourse Fichier VoitureCourse2.cs

Par exemple, via un gnrateur de code (prenons par exemple LINQ for SQL), on gnre une classe. Cette classe contient des membres pour lesquels il nest pas possible de dfinir une implmentation lors de la gnration. Le gnrateur de code ne gnre alors que la signature de la mthode, et les appels de cette mthode dans la mme classe. Cette implmentation ne peut tre fournie que par le dveloppeur 2. Ce dernier, au lieu de la fournir dans le fichier gnr (ces Dotnet France Association James RAVAILLE

Les nouveauts du langage C# 3.0 modifications pourraient tre perdues lors dune prochaine gnration de la classe), va la fournir en dfinissant la mme mthode partielle dans une autre partie de la classe partielle.

3.2 Exemple de mise en uvre


Voici un exemple de mthodes partielles :
// C# partial class VoitureCourse { #region Attributs et accesseurs private string _NumeroImmatriculation; public string NumeroImmatriculation { get { return _NumeroImmatriculation; } set { _NumeroImmatriculation = value; } } public string Marque { get; set; } #endregion #region Constructeurs public VoitureCourse(string aNumeroImmatriculation, string aMarque) { this.NumeroImmatriculation = aNumeroImmatriculation; this.Marque = aMarque; this.Demarrer(); } #endregion #region Methodes partial void Demarrer(); #endregion }

La mthode Demarrer est une mthode partielle. Cette mthode est appele dans le constructeur de la mme classe. Nous avons vu prcdemment, que limplmentation de la mthode partielle dans lautre classe partielle est optionnelle. Si on observe le code C# rtro-compil de lassembly contenant cette classe avec loutil Reflector (http://www.redgate.com/products/reflector), alors on peut observer que lappel de la mthode Dmarrer, est prsent uniquement si limplmentation est ralise dans une autre partie de la classe partielle. Voici un exemple dimplmentation de la mthode Dmarrer. Cette mthode aussi ne doit pas tre dfinit avec un niveau de visibilit, et doit avoir la mme signature que la mthode prcdemment dfinie :

Dotnet France Association James RAVAILLE

Les nouveauts du langage C# 3.0

// C# partial void Demarrer() { Console.WriteLine("La voiture " + this.NumeroImmatriculation + " a dmarr"); }

Dotnet France Association James RAVAILLE

Les nouveauts du langage C# 3.0

4 Les initialiseurs dobjets et de collections


4.1 Prsentation
Le rle des initialiseurs dobjets, est de simplifier lcriture de la cration dobjets partir dune classe ou dun type anonyme, en combinant dans la mme instruction : Linstruction de la cration de lobjet. Linitialisation de ltat de lobjet (soit lensemble des attributs).

Les initialiseurs de collection permettent de dfinir quels sont les lments qui constituent cette collection, lors de son instanciation. Ils permettent ainsi de simplifier la cration et lalimentation dune collection de donnes ou dobjets.

4.2 Exemple de mise en uvre


4.2.1 Les initialiseurs dobjets Soit la classe Voiture suivante :

// C# partial class VoitureCourse { #region Attributs et accesseurs private string _NumeroImmatriculation; public string NumeroImmatriculation { get { return _NumeroImmatriculation; } set { _NumeroImmatriculation = value; } } public string Marque { get; set; } #endregion #region Constructeurs public VoitureCourse(string aNumeroImmatriculation) { this.NumeroImmatriculation = aNumeroImmatriculation; this.Marque = string.Empty; this.Demarrer(); } public VoitureCourse() : this(string.Empty) { } #endregion #region Methodes partial void Demarrer(); #endregion }

Dotnet France Association James RAVAILLE

10

Les nouveauts du langage C# 3.0

Voici un bloc dinstruction C#, permettant de crer une instance de cette classe, en utilisant un constructeur dfini dans la classe, et linitialiseur dobjets :
// C# Voiture oVoiture ; oVoiture = new Voiture() { Marque = "Renault", NumeroImmatriculation = "212 YT 44" };

Via linitialisation dobjet, il est ainsi possible dans la mme instruction, de crer une instance de la classe VoitureCourse en utilisant lun des deux constructeurs prsents dans la classe, et dinitialiser tous les attributs souhaits. A noter que le constructeur est toujours appel avant linitialisation des attributs.

4.2.2

Les initialiseurs de collections Voici un exemple, montrant commun crer une collection de nombre entiers :

// C# List<int> oListeEntiers = new List<int>() { 1, 3, 4, 6, 90, 34 };

Voici un autre exemple, montrant comment crer une collection dobjets de type VoitureCourse :
// C# List<Voiture> oListeVoitures = new List<VoitureCourse>() { new VoitureCourse ("34 YT 54"), new VoitureCourse ("17 RE 33"), new VoitureCourse ("106 IU 75") {Marque="Peugeot"} };

Lexemple ci-dessus, vous montre quil est aussi possible dutiliser linitialisation dobjets, dans une instruction utilisant linitialisation de collections.

Dotnet France Association James RAVAILLE

11

Les nouveauts du langage C# 3.0

5 Linfrence de type et les types anonymes


5.1 Prsentation de linfrence de type
Linfrence de type permet de dclarer une variable locale sans prciser son type. Cependant, cette variable doit obligatoirement tre initialise, afin que le compilateur puisse dterminer son type, partir de la valeur ou lexpression dinitialisation. Une fois la variable dclare, on peut lui appliquer tous les membres, exposs par le type automatiquement dtermin. Je pense que linfrence de type, doit uniquement tre utilise quand il nest pas possible ou trs difficile de dtermin le type de la variable partir de sa valeur dinitialisation. Cette situation peut se produire dans deux cas : Lorsquun type anonyme est utilis dans la valeur dinitialisation. Cest le cas lors de la ralisation de projection de donnes dans les requtes LINQ. Lorsque le type de la valeur dinitialisation est complexe, et donc difficilement dfinissable par tout dveloppeur. Linfrence de type est mise en uvre au travers du mot cl var.

5.2 Prsentation des types anonymes


Le langage C# 2.0 introduisait les mthodes anonymes. Le langage C# 3.0 introduit les types anonymes. Il ny a pas de relation directe entre ces deux notions. Les types anonymes permettent de crer des objets et des collections dobjets, sans avoir dfinir explicitement dans lapplication, la classe utilise pour crer les objets. Cest le compilateur qui se charge de gnrer dynamiquement la classe, lors de la compilation du code. Lutilisation de cette nouveaut entraine lutilisation implicite de linitialisation dobjets et de collections, ainsi que de linfrence de types. On retrouve lutilisation de toutes ces nouveauts dans lcriture de requtes LINQ. Les types anonymes correspondent uniquement des structures de donnes en mmoire. Ils ne peuvent contenir des mthodes, applicables aux objets quils permettent de crer. Comme toutes classes, les types anonymes drivent de la classe System.Object. Les seules mthodes alors applicables ces objets sont ceux hrits de cette mme classe. La mise en uvre des types anonymes est ralise au travers de la syntaxe suivante : new { proprit = valeur , }

5.3 Exemple de mise en uvre


Voici un exemple de code, permettant de crer un objet nomm oVoiture partir dun type anonyme. La structure de cet objet est dtermine par les attributs qui sont dfinis et valoriss entre accolades. Cet exemple met en vidence un exemple dutilisation des initialiseurs dobjets :

Dotnet France Association James RAVAILLE

12

Les nouveauts du langage C# 3.0

// C# var oVoiture = new { Marque = "Renault", NumeroImmatriculation = "212 YT 44", Couleur = Color.Black };

Il est alors possible de crer des objets, contenant uniquement des donnes, sans avoir implmenter dans le code la classe permettant de les crer. On remarque lutilisation du mot cl var, marquant lutilisation de linfrence de type.

Voici un autre exemple, qui montre lutilisation de linfrence de type, dun type anonyme et linitialisation dobjets. La requte LINQ permet dobtenir une collection dobjets, o chacun contient une marque de voiture et un numro de dpartement, partir dune collection de voitures. Seules les voitures immatricules dans les dpartements 44 et 35, doivent tre slectionnes :
// C# var oListeVoitures1 = (from oVoiture in oListeVoitures where oVoiture.NumeroImmatriculation.EndsWith("44") || oVoiture.NumeroImmatriculation.EndsWith("35") select new { Marque = oVoiture.Marque, Departement = oVoiture.NumeroImmatriculation.Substring(oVoiture.NumeroImmatriculation.L ength - 2) }).ToList();

Dotnet France Association James RAVAILLE

13

Les nouveauts du langage C# 3.0

6 Les mthodes dextension


6.1 Prsentation
Les mthodes dextension permettent dtendre une classe, en ajoutant de nouvelles mthodes, sans crer de classe drive de cette mme classe. Elles sont utiles dans les cas suivants : Soit une interface IVehicule, qui dfinit les membres de toutes classes permettant de crer des objets, qui se considrent comme tant des vhicules. Soit les classes Voiture, Camion, Velo, Moto, qui implmentent cette interface.

Alors si on tend linterface IVehicule par une mthode dextension, alors cette mthode dextension est applicable toutes les instances, cres partir des classes implmentant cette interface.

Vous dveloppez une application, qui utilise des classes contenues dans un assembly qui vous a t fourni. Vous ne possdez pas les sources de cet assembly. Vous savez quil contient une classe Animal, qui possde des classes drives. Vous souhaitez alors ajouter des membres supplmentaires cette classe, afin denrichir les classes drives. Comme vous ne possdez pas les sources de lassembly, vous ne pouvez le faire autrement quen crant des mthodes dextension, qui tendent la classe Animal.

En C#, une mthode dextension est une mthode statique, contenue dans une classe statique. Cette mthode sera utilise : Comme toute mthode statique, en passant en paramtre lobjet laquelle elle sapplique. Ainsi dans lcriture du code, il est possible dexcuter linstruction suivante sans la leve dune exception de type NullReferenceException, mme si lobjet oVoiture est null ; la mthode Garer sera appele, avec la valeur null en paramtre :

Dotnet France Association James RAVAILLE

14

Les nouveauts du langage C# 3.0

// C# oVoiture.Garer();

Comme toute autre mthode dinstance de la classe tendue.

La signature de cette mthode est particulire : le type du premier paramtre est prfix du mot cl this, et ce type reprsente le type tendu. Une mthode dextension peut possder des paramtres dentre, qui sont alors ajouts la suite de ce premier paramtre.

6.2 Exemple de mise en uvre


Voici une mthode dextension permettant dtendre le type System.Int32 du Framework .NET :
// C# public static class IntExtension { public static string MultiplierParDeux(this int aNombre) { return aNombre.ToString() + " * 2 = " + (aNombre * 2).ToString(); } }

Elle permet de multiplier par deux le contenu de toute variable de type System.Int32. Voici un exemple :
// C# int i = 10; Console.WriteLine(i.MultiplierParDeux()); => Affiche 10 * 2 = 20

Un autre exemple : toutes les classes reprsentant un dictionnaire de donnes, dit gnrique implmente linterface IDictionary<TKey, TValue> du Framework .NET. Alors voici une mthode permettant dtendre toute collection de donnes, implmentant cette interface, de manire pouvoir accder la valeur dun lment partir de sa cl, ou obtenir une valeur par dfaut, si aucun lment de la collection nest identifi avec la cl :

Dotnet France Association James RAVAILLE

15

Les nouveauts du langage C# 3.0

// C# public static class IDictionnaryExtension { public static TValue GetValue<TKey, TValue>( this IDictionary<TKey, TValue> aListe, TKey key, TValue defaultValue) { TValue aValeurRetour; if (aListe.ContainsKey(key)) aValeurRetour = aListe[key]; else aValeurRetour = defaultValue; return aValeurRetour; } }

Et voici un exemple dutilisation de la mthode dextension, avec la classe gnrique Dictionary<TKey, TValue>, qui implmente linterface gnrique IDictionary<TKey, TValue> :
// C# // Cration de la collection de donnes. Dictionary<int, string> oListeFormations = new Dictionary<int, string>(); oListeFormations.Add(1, "Formation C#"); oListeFormations.Add(2, "Formation ASP .NET"); oListeFormations.Add(3, "Atelier Accs aux donnes"); oListeFormations.Add(4, "La scurit dans les applications .NET"); // Utilisation de la mthode dextension. string sFormation = oListeFormations.GetValue(5, "formation inexistante");

Le corps des mthodes dextension peut tre paramtrables , personnalisables , au travers de lutilisation dexpressions lambda.

6.3 Rgles particulires


Soit le diagramme de classes suivant :

Dotnet France Association James RAVAILLE

16

Les nouveauts du langage C# 3.0 Voici quelques rgles observer lors de lutilisation de mthodes dextension : Si les classes IVehiculeExtension et ITransporteurExtension possdent une mthode dextension de mme nom et avec une signature analogue , alors une erreur survient lors de la compilation, lorsque cette mthode est applique une instance de la classe Vehicule. Si la classe Vehicule contient une mthode, et que la classe IVehiculeExtension et/ou ITransporteurExtension propose une mthode dextension de mme nom et avec une signature analogue , alors lapplication compile et la mthode de la classe Vehicule masque les mthodes dextension.

Dotnet France Association James RAVAILLE

17

Les nouveauts du langage C# 3.0

7 Les expressions lambda


7.1 Prsentation
Une expression lambda est une fonction ne possdant pas de nom (cela rappel les mthodes anonymes introduites dans le langage C# 2.0), excutant un traitement et retournant une valeur. Une expression lambda est compose de trois parties : Une liste de paramtres Loprateur => Une expression Dans quels cas peut-on utiliser les expressions lambda : Pour raliser des fonctions de calcul. Largement utilises dans les mthodes dextension de linterface IEnumerable<T>.

7.2 Exemple de mise en uvre


Par exemple, vous manipulez une liste dentiers. Et dans cette liste, vous souhaitez uniquement slectionner les nombres pairs. Avec le langage C# 2.0, on crira le bloc de code suivant :
// C# List<int> oListeNombres = new List<int>() { 1, 34, 3, 9, 12, 18}; List<int> oListeNombrePaires = new List<int>(); foreach (int i in oListeNombres) { if (i % 2 == 0) oListeNombrePaires.Add(i); }

Avec le langage C# 3.0, en utilisant la mthode dextension Where de linterface gnrique IEnumerable<T>, on crirait le bloc de code suivant :
// C# List<int> oListeNombres = new List<int>() { 1, 34, 3, 9, 12, 18}; List<int> oListeNombrePaires; oListeNombrePaires = oListeNombres.Where(i => i % 2 == 0).ToList();

Le bloc de code C# ci-dessus utilise la mthode dextension Where, tendant linterface gnrique IEnumarable<T> du Framework .NET. Cette mthode permet de filtrer la collection dentiers, en fonction dune expression boolenne. Cette expression boolenne est dfinie via lexpression lambda i => i % 2 == 0, qui signifie pour tous les nombres i de la collection pour lesquels le rsultat du modulo par deux vaut 0 . Dotnet France Association James RAVAILLE

18

Les nouveauts du langage C# 3.0

7.3 Utilisation des expressions lambda comme paramtre de mthode


Dans une mthode classique ou une mthode dextension, il est possible de paramtrer , personnaliser le comportement de la mthode, en utilisant une expression lambda. Voici une mthode dextension, permettant de parcourir une liste dentiers laquelle elle est applique, afin de les traiter. Le traitement de ces entiers nest pas dtermin dans la mthode dextension elle-mme, mais par le code utilisant cette mthode dextension :
// C# public static void TraiterElements(this List<int> aListe, Func<int, int> aExpression) { for (int i=0; i<aListe.Count; i++) { aListe[i] = aExpression(i); } }

Pour dfinir une expression lambda, il suffit dutiliser le mot cl Func permettant de dfinir des types de donnes (une volution des dlgus). Dans lexemple prcdent, Func<int, int> dcrit une expression de traitement acceptant une donne de type int en paramtre (le premier type prcis), effectuant un traitement avec ou sur ce paramtre, et retournant une donne de type int (second type de donne dfini).

Enfin, voici deux blocs de code utilisant la mthode TraiterElements sur une collection dentiers, afin de multiplier par 2 chacun des nombres de la collection :
// C# // Premier exemple. Func<int, int> oExpressionTraitement = (i) => i * 2; oListeNombres.TraiterElements(oExpressionTraitement); // Second exemple. oListeNombres.TraiterElements((i) => i * 2);

Dotnet France Association James RAVAILLE

19

Les nouveauts du langage C# 3.0

8 Conclusion
Ce chapitre vous a prsent les nouveauts du langage C# 3.0. Ces nouveauts ont t ncessaires, afin de permettre dcrire des requtes LINQ (sur une grappe dobjets, sur une base de donnes SQL Server, ou sur un flux XML), et lutilisation de composants daccs aux donnes tels que Classes LINQ For SQL. Voici un exemple, qui rcapitule et combine de nombreuses nouveauts du langage C# 3.0, au travers dune requte LINQ : crire une requte LINQ, permettant de slectionner la liste des fichiers dextension txt dun rpertoire, dont la taille est strictement suprieure 10 Ko. En sortie, on doit obtenir uniquement le nom et la taille des fichiers en octets, dans lordre alphabtique invers sur le nom :
// C# DirectoryInfo oDirInfo = new DirectoryInfo(@"c:\transfert"); // Slection de la liste des fichiers (requte LINQ). var oListeFichiers = oDirInfo.GetFiles("*.txt") .Where(oFichier => oFichier.Length > 10 * 1024) .OrderByDescending(oFichier => oFichier.Name) .Select(oFichier => new { oFichier.Name, Taille = oFichier.Length }); // Affichage de la liste des fichiers. foreach (var oFichier in oListeFichiers) { Console.WriteLine(oFichier.Name + " : " + oFichier.Taille.ToString()); }

La requte LINQ prsente dans le bloc de code ci-dessus, utilise pleinement les nouveauts du langage C# 3.0 que nous avons tudies dans ce support : Infrence de type : lie lutilisation du type anonyme, et marque par lutilisation du mot cl var. Mthodes dextension : marques par lutilisation des mthodes dextension Where, OrderByDescending, et Select de linterface gnrique IEnumerable<T> du Framework .NET. Type anonyme : marque par lutilisation du mot cl new, et la projection de donnes effectue en ne slectionnant que le nom et la taille du fichier en octets. Expressions lambda : utilises dans les trois mthodes dextension. Autrement dit, pour filtrer, trier les fichiers, et raliser une projection de donnes sur les informations des fichiers. Initialisation dobjet : utilise au sein du type anonyme.

Dotnet France Association James RAVAILLE