41. Un opérateur de conversion de type est contravariant s’il ordonne les types du plus générique au plus spécifique
42. Si tu sais comparer deux « object », alors tu sauras aussi comparer deux « EventArgs ». Ainsi, si tu as besoin d’un comparateur d’EventArgs, alors je peux te donner un comparateur d’objet
43. Co & Contra Variance – Les delegates – 1/2 public class Employé { } public class Développeur : Employé { } class Program { staticEmployé CréeEmployé() { return null; } staticDéveloppeur CréeDéveloppeur() { return null; } staticvoid Main(string[] args) { var créeEmployé = new Func<Employé>(CréeEmployé); Employé employé1 = créeEmployé(); var créeDeveloppeur = new Func<Employé>(CréeDéveloppeur); Employé employé2 = créeDeveloppeur(); } } public class Employé { } public class Développeur : Employé { } class Program { staticEmployé CréeEmployé() { return null; } staticDéveloppeur CréeDéveloppeur() { return null; } } Func<Employé> Func<Développeur> Les delegates sontcovariants
44. Co & Contra Variance – Les delegates – 2/2 delegatevoidEventHandler(objectsender, EventArgse); TextBoxtxtBox = new TextBox(); txtBox.Click += txtBox.KeyDown += delegatevoidKeyEventHandler(objectsender, KeyEventArgse); voidMonHandler(objectsender, EventArgse) { } TextBoxtxtBox = new TextBox(); txtBox.Click += MonHandler; txtBox.KeyDown += MonHandler; Les delegates sontcontravariants
45. Covariance des tableaux Les arrays sontcovariants… string[] strArray = new[] { "A", "B" }; object[] objArray = strArray; …mais pas “type safe” objArray[0] = 12; string s = strArray[0]; System.ArrayTypeMismatchException Possible seulement pour les types références Il s’agiticid’une conversion par “boxing” Interdit int[] intArray = new[] { 1, 2, 3}; object[] objArray = intArray;
46. Co & Contra Variance des types génériques – 1/4 Génériques = Sécurité de typage List<string> strArray = newList<string> { "A", "B" }; List<object> objArray = strArray; Non « Type Safe » donc non covariant List<string> strArray = newList<string> { "A", "B" }; IEnumerable<object> objEnum = strArray; « Type Safe » donc covariant
47. Co & Contra Variance des types génériques – 2/4 public voidTestContravariance(IComparer<string> comparer) { comparer.Compare("chaine 1", "chaine 2"); } public class MyObjectComparer : IComparer<object> { ... } public class MyStringComparer: IComparer<string> { ... } IComparer<string> stringComparer = new MyStringComparer(); stringComparer.Compare("chaine 1", "chaine 2"); IComparer<object> objectComparer = new MyObjectComparer(); objectComparer.Compare("chaine 1", "chaine 2") IComparer<T> est contravariant IComparer<string> stringComparer = new MyStringComparer(); IComparer<object> objectComparer = new MyObjectComparer(); TestContravariance(stringComparer); TestContravariance(objectComparer);
48.
49. T ne doit être utilisé que comme type de retour
60. Paramètres Optionnels et Nommés – 1/4 Une méthode principale FileStream Open(string path, FileModemode, FileAccessaccess, FileShareshare) FileStream Open(string path, FileModemode, FileAccessaccess) FileStream Open(string path, FileModemode) Plusieurs overloads Redirection avec des valeurs par défaut
61. Paramètres Optionnels et Nommés – 2/4 public voidMethode(intx, inty = 5, intz = 10) { } 2 paramètres optionnels Methode(10, 2, 15); Methode(10, 2); //Equivalent à Methode(10, 2, 10); Methode(10); //Equivalent à Methode(10, 5, 10); Methode(10, , 15); //INTERDIT Les paramètres omis doivent être en dernier
62. Paramètres Optionnels et Nommés – 3/4 Les paramètres nommées doivent être en dernier Methode(10, z: 15); Les paramètres non optionnelsdoivent être spécifiés Methode(y: 15, x: 10); Methode(y: 15, x: 10, z: 2); Les paramètres nommés peuvent être dans n’importe quel ordre Les paramètres nommés sont évalués dans l’ordre d’écriture
85. Créer un type dynamique – 2/2 public class MonDynamicObject : DynamicObject { Dictionary<string, object> dic = new Dictionary<string, object>(); public overrideboolTryGetMember(GetMemberBinder binder, out objectresult) { return this.dic.TryGetValue(binder.Name, out result); } public overrideboolTrySetMember(SetMemberBinder binder, objectvalue) { this.dic[binder.Name] = value; return true; } } dynamicmonObjet = new MonDynamicObject(); monObjet.Nom = "Dautreppe"; monObjet.Prenom = "Pierre-Emmanuel"; Console.WriteLine(monObjet.Prenom + " " + monObjet.Nom);
86. Types dynamiques – Utilisation de la classe Expando staticvoidMain() { dynamicpersonne = new ExpandoObject(); //1. Définir des propriétés personne.Nom = "Dautreppe"; personne.Prenom = "Pierre-Emmanuel"; //2. Définir des méthodes personne.ToString = new Func<string>( () => personne.Nom + " " + personne.Prenom ); Console.WriteLine(personne.ToString()); //3. Définir un évènement personne.MonEvent = null; personne.OnMonEvent = new Action<EventArgs>((e) => { if (personne.MonEvent != null) personne.MonEvent(personne, e); }); personne.MonEvent += new EventHandler(MonEventHandler); personne.OnMonEvent(EventArgs.Empty); } privatestaticvoidMonEventHandler(dynamicobj, EventArgs e) { Console.WriteLine("MonEvent appelé sur '" + obj.ToString()); }
87. Types dynamiques – Conclusion – 1/2 Que peut-on appeler ? Toute méthode définie sur l’instance Méthode publique Méthode protected Méthode private (de l’instance) Méthode d’interface (si implémentation implicite) Que ne peut-on pas appeler ? Toute méthode « n’existant pas » sur l’instance Méthode private (d’une classe de base) Méthode static (quelque soit sa visibilité) Méthode d’interface (si implémentation explicite) Méthode d’extension
116. BCL – Tuples – 2/2 « new Tuple » et « Tuple.Create » sont équivalents presque !! var a = newTuple<int, int, int, int, int, int, int, Tuple<int, int>> (1, 2, 3, 4, 5, 6, 7, newTuple<int, int>(8, 9)); var b = Tuple.Create(1, 2, 3, 4, 5, 6, 7, Tuple.Create(8, 9)); var a = newTuple<int, int, int, int, int, int, int, Tuple<int, int>> (1, 2, 3, 4, 5, 6, 7, newTuple<int, int>(8, 9)); var b = Tuple.Create(1, 2, 3, 4, 5, 6, 7, Tuple.Create(8, 9)); Console.WriteLine(a.Item5); // 5 Console.WriteLine(a.Rest.Item2); // 9 var a = newTuple<int, int, int, int, int, int, int, Tuple<int, int>> (1, 2, 3, 4, 5, 6, 7, newTuple<int, int>(8, 9)); var b = Tuple.Create(1, 2, 3, 4, 5, 6, 7, Tuple.Create(8, 9)); Console.WriteLine(a.Item5); // 5 Console.WriteLine(a.Rest.Item2); // 9 Console.WriteLine(b.Item5); // 5 Console.WriteLine(b.Rest.Item1.Item2); // 9 Rest = Tuple<int, int> Rest = Tuple<Tuple<int, int>>
117. BCL – Améliorations à System.IO string[]GetFiles(string path, string searchPattern); var errorlines = fromfile in Directory.GetFiles(@"C:ogs", "*.log") fromline in File.ReadAllLines(file) whereline.StartsWith("Error:") select string.Format("File={0}, Line={1}", file, line); File.WriteAllLines(@"C:rrorlines.log", errorlines); string[]ReadAllLines(string path); void WriteAllLines(string path, string[] contents); IEnumerable<string>EnumerateFiles(string path, string searchPattern); var errorlines = fromfile in Directory.EnumerateFiles(@"C:ogs", "*.log") fromline in File.ReadLines(file) whereline.StartsWith("Error:") select string.Format("File={0}, Line={1}", file, line); File.WriteAllLines(@"C:rrorlines.log", errorlines); IEnumerable<string>ReadLines(string path); void WriteAllLines(string path, IEnumerable<string> contents);
118.
119.
120. Simplification pour IPC (Inter-Process Communication) Taille de la vue <= Mémoire disponible pour mapping (2Gb sur 32 bits) Stream (lecture séquentielle) Accessor (lecture aléatoire) Process 1 Process 2
121. BCL – Fichiers mappés en mémoire – 2/2 Process 1 using(var mmf = MemoryMappedFile.CreateNew("FichierMappé", 1000)) { using(var stream = mmf.CreateViewStream()) new BinaryWriter(stream).Write("Bonjour"); var startInfo = new ProcessStartInfo("AutreProcess.exe"); startInfo.UseShellExecute = false; Process.Start(startInfo).WaitForExit(); } Ou mmf.CreateViewAccessor Process 2 using(var mmf = MemoryMappedFile.OpenExisting("FichierMappé")) { using(var stream = mmf.CreateViewStream()) Console.WriteLine(new BinaryReader(stream).ReadString()); }
154. System.Numerics – 1/2 Une nouvelle DLL : System.Numerics.dll BigInteger Un entier, « arbitrairement grand » Complex Structure pour représenter des nombres complexes
184. C# 5.0 (?) : « Compiler As A Service »Tout simplement une nouvelle révolution
185. Merci à tous ! N’oubliez pas votre formulaire de participation au concours! Prochains évènements 09/03 : Windows Live Meeting – VS 2010 - .NET 4.0 23/03 : MyTIC : Sharepoint 2010 30/03 au 01/04 : Tech Days 2010 21/04 : DotNetHub : Méthodes Agiles 28/04 : DotNetHub : NService Bus
Notas do Editor
Doivent être des constantes de compilation : On ne peut donc pas définir comme valeur par défaut un appel de méthode, …Notez que si on veut assigner une méthode à un delegate, on doit « référencer » tous ses paramètres
La DLR a été créée pour IronPythonPuis a été sortie dans une DLL séparée de façon à pouvoir l’utiliser dans d’autres langages dynamiquesEt enfin intégré à .NET 4.0Si on traite avec des dynamiques, le compilateur émet un « dynamic call site » à la place d’un appel direct de méthode.« DynamicDispatch » = appel de la méthode à l’exécution en utilisant le binder adéquat
Conversions existantes : implicit, explicit, user-defined, boxing, reference, …Conversion d’assignation : quand on assigne un dynamic vers un type « réel »Conversion structurelle : For a given T, let red(T) ("T reduced") be the type T except with all the occurrences of dynamic replaced by object. So red(Dictionary<dynamic, object>) == Dictionary<object,object>. We added the following conversions.If there is an implicit reference conversion from red(S) to red(T), then there is also an implicit reference conversion from S to T, except in the case where S is dynamic and T is object. If there is an implicit reference conversion from S to T and from T to U, and one of them is a conversion added by rule 1, then there is an implicit conversion from S to U. If there is an explicit reference conversion from red(S) to red(T), then there is also an explicit reference conversion from S to T.
Attention, ne peut pas être utilisé avec IronPython pour le moment : Breaking Changes dans la DLR dans la version de .NET 4.0 Beta 1 Génère un AttributeError
Utilise toujours le minimum de mémoire quelque soit le nombre de fichiers / lignes / répertoires
StaticChecker : Team System uniquementAttention : l’API est disponible dans le .NET Framework 4.0, mais on doit installer CodeContracts malgré tout si on veut avoir l’onglet « Contract » dans les propriétés du projet, et les activer
SpinLock : lock mais qui ne va pas mettre le thread en « idle » s’il ne peut l’acquérir. Au contraire va boucler jusqu’à l’obtenir. Meilleures performances si le temps d’attente est court (mise en « idle » est couteux)
TFS : baisse des contraintes, installable sur un poste client