C# 4.0 et les améliorations à la BCL Pierre-Emmanuel Dautreppe – 04 Mars 2010 pierre@dotnethub.be – www.pedautreppe.com – @pedautreppe Découvrez le framework .NET 4.0 : les apports au langage Quelques améliorations de la « Base Class Library »
Evolution du langage C# 3.5 (3.0: Nov. 2006) (3.5: Nov. 2007) C# 2.0 C# 1.0 : Toute la base Code Managé Common Type System Programmation Orientée Objets Méthodes, Propriétés, Indexeurs, Evènements Compatibilité avec autres technologies Interopérabilité COM P/Invoke Code Unsafe C# 2.0 : Génériques Apparition des génériques : type safety Correction de manques Types nullables Classes statiques Simplifications Méthodes anonymes Itérateurs (yield) Evolution du langage C# 1.0 (Nov. 2001) C# 2.0 (Oct. 2005) C# 3.5 (3.0: Nov. 2006) (3.5: Nov. 2007) (3.5sp1: Nov.2008) C# 3.5 : LINQ et méthodes lambdas LINQ Programmation déclarative Concis, mais statiquement typé Méthodes Lambdas Programmation fonctionnelle Meta-Programmation Le code devient une donnée Expression Trees
Tendances d’évolution de .NET Programmation Déclarative Quoi Comment Impératif Déclaratif Tendances d’évolution de .NET Programmation Déclarative Progammation Dynamique Concurrence / Parallélisation foreach ( int i in list ) if ( i > 10 ) result.Add(i); result.Sort(); from i in list where i > 10 orderby i select i Concurrence / Parallélisation Architectures multi-cœur Serveurs multi-processeurs Tirer parti de l’amélioration possible des performances en se reposant sur des frameworks en programmant différement Simplifier la prise en compte de la parallélisation Programmation Dynamique Ecriture Dynamique Typage Implicite Simple et succinct Pas de compilation Meta-programmation Ecriture Statique Sécurité de typage Outils Intelligents (refactoring, …) Performant Meilleure montée en charge
Agenda C# 4.0 Co & Contra Variance des génériques Paramètres nommés et optionnels Types dynamiques Interopérabilité COM Améliorations à la Base Class Library Conclusion Agenda C# 1.0 C# 2.0 C# 3.0 C# 1.0 C# 2.0 C# 3.0 C# 4.0
C# 4.0 Co & Contra Variance des génériques Paramètres nommés et optionnels Types dynamiques Interopérabilité COM Améliorations à la Base Class Library Conclusion
Co & Contra Variance – Définition Covariance Un opérateur de conversion de type est covariant s’il ordonne les types du plus spécifique au plus générique Si tu me fournis une SqlCommand, alors je peux me contenter de la traiter comme une DbCommand Contravariance Un opérateur de conversion de type est contravariant s’il ordonne les types du plus générique au plus spécifique 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
Co & Contra Variance – Les delegates – 1/2 public class Employé { } public class Développeur : Employé { } class Program { static Employé CréeEmployé() { return null; } static Développeur CréeDéveloppeur() { return null; } } public class Employé { } public class Développeur : Employé { } class Program { static Employé CréeEmployé() { return null; } static Développeur CréeDéveloppeur() { return null; } static void 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(); } Func<Employé> Func<Développeur> Les delegates sont covariants
Co & Contra Variance – Les delegates – 2/2 delegate void EventHandler(object sender, EventArgs e); TextBox txtBox = new TextBox(); txtBox.Click += txtBox.KeyDown += delegate void KeyEventHandler(object sender, KeyEventArgs e); void MonHandler(object sender, EventArgs e) { } TextBox txtBox = new TextBox(); txtBox.Click += MonHandler; txtBox.KeyDown += MonHandler; Les delegates sont contravariants
Covariance des tableaux Les arrays sont covariants… 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’agit ici d’une conversion par “boxing” Interdit int[] intArray = new[] { 1, 2, 3}; object[] objArray = intArray;
Co & Contra Variance des types génériques – 1/4 Génériques = Sécurité de typage List<string> strArray = new List<string> { "A", "B" }; List<object> objArray = strArray; Non « Type Safe » donc non covariant List<string> strArray = new List<string> { "A", "B" }; IEnumerable<object> objEnum = strArray; « Type Safe » donc covariant
Co & Contra Variance des types génériques – 2/4 public void TestContravariance(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);
Co & Contra Variance des types génériques – 3/4 public interface IEnumerable<out T> : IEnumerable { IEnumerator<T> GetEnumerator(); } Mot-clé « out » T ne doit être utilisé que comme type de retour IEnumerable<T> est covariant IEnumerable<B> est considéré comme IEnumerable<A> si conversion de référence de B vers A A B IEnumerable<A> IEnumerable<B>
Co & Contra Variance des types génériques – 4/4 public interface IComparer<in T> { int Compare(T x, T y); } Mot-clé « in » T ne doit être utilisé que comme paramètre d’input IComparer<T> est contravariant IComparer<A> est considéré comme IComparer<B> si conversion de référence de B vers A A B IComparer<A> IComparer<B>
Interfaces Delegates Variance en .NET 4.0 System.Collections.Generic.IEnumerable<out T> System.Collections.Generic.IEnumerator<out T> System.Linq.IQueryable<out T> System.Collections.Generic.IComparer<in T> System.Collections.Generic.IEqualityComparer<in T> System.IComparable<in T> Delegates System.Func<in T, …, out R> System.Action<in T, …> System.Predicate<in T> System.Comparison<in T> System.EventHandler<in T>
C# 4.0 Co & Contra Variance des génériques Paramètres nommés et optionnels Types dynamiques Interopérabilité COM Améliorations à la Base Class Library Conclusion
Paramètres Optionnels et Nommés – 1/4 Une méthode principale FileStream Open(string path, FileMode mode, FileAccess access, FileShare share) FileStream Open(string path, FileMode mode, FileAccess access) FileMode mode) Plusieurs overloads Redirection avec des valeurs par défaut
Paramètres Optionnels et Nommés – 2/4 public void Methode(int x, int y = 5, int z = 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
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 optionnels doivent ê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
Paramètres Optionnels et Nommés – 4/4 Identique à VB.NET Paramètres optionnels Doivent être des constantes de compilation Valeur par défaut copiée dans l’appel Paramètres nommés La compilation se base sur les noms Ne changez pas votre API Même question que pour const ou static readonly 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 A utiliser plutôt en temps que client
C# 4.0 Co & Contra Variance des génériques Paramètres nommés et optionnels Types dynamiques Interopérabilité COM Améliorations à la Base Class Library Conclusion
Exemples appels « dynamiques » avec C# 3.5 Calculator calc = GetCalculator(); int resultat = calc.Add(10, 20); object calculator = GetCalculator(); Type calcType = calculator.GetType(); int result = (int)calcType.InvokeMember("Add", BindingFlags.InvokeMethod, null, calculator, new object[] { 10, 20 }); C# C# ScriptObject calc = GetCalculator(); int resultat = (int)calc.Invoke("Add", 10, 20); Silverlight Javascript ScriptScope python = Python.CreateRuntime().UseFile("Calculator.py"); ScriptEngine engine = python.Engine; int resultat = (int)engine.Execute ("GetCalculator().Add(10, 20)", python); C# IronPython
Dynamic Language Runtime (DLR) IronPython IronRuby C# Visual Basic Autres… Dynamic Language Runtime (DLR) Expression Trees Dynamic Dispatch Call Site Caching POCO Binder JavaScript Binder Python Binder Ruby Binder COM Binder La DLR a été créée pour IronPython Puis a été sortie dans une DLL séparée de façon à pouvoir l’utiliser dans d’autres langages dynamiques Et enfin intégré à .NET 4.0 Si on traite avec des dynamiques, le compilateur émet un « dynamic call site » à la place d’un appel direct de méthode. « Dynamic Dispatch » = appel de la méthode à l’exécution en utilisant le binder adéquat <
Types dynamiques – 1/3 Calculator calc = GetCalculator(); int resultat = calc.Add(10, 20); Statiquement typé comme “dynamic” dynamic calc = GetCalculator(); int resultat = calc.Add(10, 20); Conversion dynamique de la valeur de retour Appel dynamique de la méthode
Types dynamiques – 2/3 Quand les opérandes sont dynamic… Type statique (à la compilation) Type dynamique(à l’exécution) dynamic Int32 dynamic x = 1; dynamic y = "Bonjour"; dynamic z = new List<int> { 1, 2, 3 }; dynamic String dynamic List<int> Quand les opérandes sont dynamic… La sélection des membres est différée à l’exécution A l’exécution, dynamic est remplacé par le type réel de chaque membre Le type de retour de l’opération est également dynamic
Types dynamiques – 3/3 public class Calculator { public double Add(double a, double b) { ... } public int Add(int a, int b) { ... } } Calculator calc = GetCalculator(); double x = 2.25, y = 3.75; double result = calc.Add(x, y); A la compilation : double Add(double, double) Calculator calc = GetCalculator(); dynamic x = 2.25, y = 3.75; dynamic result = calc.Add(x, y); A l’exécution : double Add(double, double) Calculator calc = GetCalculator(); dynamic x = 2, y = 3; dynamic result = calc.Add(x, y); A l’exécution : int Add(int, int)
Types dynamiques – Points à retenir La résolution des méthodes est différée à l’exécution si nécessaire public void Methode(dynamic d) On ne peut pas appeler des méthodes d’extensions A savoir (ou non): Nouveaux types de conversion : assignation, structurelle, … dynamic n’existe pas au niveau du code IL 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.
Types dynamiques – Exemples d’écritures – 1/2 Ces écritures sont valides dynamic MaMethode(int i, dynamic d) { ... } dynamic[] monArray = ... IEnumerable<dynamic> enumerable = ... List<dynamic> liste = ... dynamic MaMethode(int i, dynamic d) { ... } dynamic[] monArray = ... IEnumerable<dynamic> enumerable = ... List<dynamic> liste = ... class BaseClass<T> { } class Derived : BaseClass<dynamic> { } dynamic MaMethode(int i, dynamic d) { ... } dynamic[] monArray = ... dynamic MaMethode(int i, dynamic d) { ... } dynamic MaMethode(int i, dynamic d) { ... } dynamic[] monArray = ... IEnumerable<dynamic> enumerable = ...
Types dynamiques – Exemples d’écritures – 2/2 Ces écritures ne sont pas valides class C : dynamic { } class C : IEnumerable<dynamic> { } class C<T> where T : BaseClass<dynamic> { } class C : dynamic { } class C : dynamic { } class C : IEnumerable<dynamic> { } Pour plus d’information : Blog de Chris Burrows http://blogs.msdn.com/cburrows/default.aspx
Créer un type dynamique – 1/2 Dans System.Core.dll Namespace System.Dynamic IDynamicObject a été renommé public class DynamicObject : IDynamicMetaObjectProvider { public virtual IEnumerable<string> GetDynamicMemberNames(); public virtual DynamicMetaObject GetMetaObject(Expression parameter); public virtual bool TryConvert(ConvertBinder binder, out object result); public virtual bool TryDeleteMember(DeleteMemberBinder binder); public virtual bool TryGetMember(GetMemberBinder binder, out object result); public virtual bool TrySetMember(SetMemberBinder binder, object value); public virtual bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result); public virtual bool TryUnaryOperation(UnaryOperationBinder binder, ... }
Créer un type dynamique – 2/2 public class MonDynamicObject : DynamicObject { Dictionary<string, object> dic = new Dictionary<string, object>(); public override bool TryGetMember(GetMemberBinder binder, out object result) return this.dic.TryGetValue(binder.Name, out result); } public override bool TrySetMember(SetMemberBinder binder, object value) this.dic[binder.Name] = value; return true; 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 dynamic monObjet = new MonDynamicObject(); monObjet.Nom = "Dautreppe"; monObjet.Prenom = "Pierre-Emmanuel"; Console.WriteLine(monObjet.Prenom + " " + monObjet.Nom);
Types dynamiques – Utilisation de la classe Expando static void Main() { dynamic personne = 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); } private static void MonEventHandler(dynamic obj, EventArgs e) Console.WriteLine("MonEvent appelé sur '" + obj.ToString());
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
Types dynamiques – Conclusion – 2/2 Quand doit-on les utiliser ? Quand on travaille sans type (par ex. réflexion) Quand on fait de l’interop COM Silverlight Javascript … Compenser des manques du Framework « INumeric » Quand ne devrait-on pas les utiliser ? Pour compenser une erreur de design Eg Coder en utilisant une classe de base, mais avoir besoin d’une connaissance des types dérivés
C# 4.0 Co & Contra Variance des génériques Paramètres nommés et optionnels Types dynamiques Interopérabilité COM Améliorations à la Base Class Library Conclusion
Interopérabilité COM – 1/3 Paramètres optionnels et nommés object fileName = "Test.docx"; object missing = System.Reflection.Missing.Value; doc.SaveAs(ref fileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing); doc.SaveAs("Test.docx"); Les APIs COM déclarent des paramètres optionnels « ref » n’est plus obligatoire
Interopérabilité COM – 2/3 COM et dynamic IExcel.Trendlines trendLines = (IExcel.Trendlines)serie.Trendlines(Type.Missing); IExcel.Range cell = (IExcel.Range)sheet.Cells[row, column]; IExcel.Trendlines trendLines = serie.Trendlines(); IExcel.Range cell = sheet.Cells[row, column]; Les APIs COM renvoient des dynamic Conversion d’assignation vers le type désiré
Interopérabilité COM – 3/3 « No PIA » : Pas de « Primary Interop Assemblies » namespace OfficeApplication { class Program static void Main(string[] args) Application excel = new Application(); Worksheet sheet = excel.Sheets.Add(); ChartObjects charts = sheet.ChartObjects(); ChartObject chart = charts.Add(10, 10, 100, 100); SeriesCollection series = chart.Chart.SeriesCollection(); Series serie = series.Add(...); Trendlines trendLines = serie.Trendlines(); Range cell = sheet.Cells[10, 10]; } Par défaut : True
Co & Contra Variance des génériques Paramètres nommés et optionnels Types dynamiques Interopérabilité COM Améliorations à la Base Class Library Conclusion TUples Code Contracts System.IO Parallel Extensions Fichiers mappés System.Numerics
BCL – Tuples – 1/2 Supporté nativement par F# et IronPython public Tuple<bool, int> TryGetElement(string key) { int valeur; bool result = dic.TryGetValue(key, out valeur); return new Tuple<bool, int>(result, valeur); } return Tuple.Create(result, valeur); System.Tuple : Factory de Tuple<...> public static class Tuple { public static Tuple<T1> Create<T1>(T1 item1); public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2); ... ... public static Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> Create<T1, T2, T3, T4, T5, T6, T7, Trest> (T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest); } De 1 à 8 types génériques Typiquement un autre Tuple<...>
BCL – Tuples – 2/2 « new Tuple » et « Tuple.Create » sont équivalents presque !! var a = new Tuple<int, int, int, int, int, int, int, Tuple<int, int>> (1, 2, 3, 4, 5, 6, 7, new Tuple<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 var a = new Tuple<int, int, int, int, int, int, int, Tuple<int, int>> (1, 2, 3, 4, 5, 6, 7, new Tuple<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 = new Tuple<int, int, int, int, int, int, int, Tuple<int, int>> (1, 2, 3, 4, 5, 6, 7, new Tuple<int, int>(8, 9)); var b = Tuple.Create(1, 2, 3, 4, 5, 6, 7, Tuple.Create(8, 9)); Rest = Tuple<int, int> Rest = Tuple<Tuple<int, int>>
BCL – Améliorations à System.IO string[] GetFiles(string path, string searchPattern); var errorlines = from file in Directory.GetFiles(@"C:\logs", "*.log") from line in File.ReadAllLines(file) where line.StartsWith("Error:") select string.Format("File={0}, Line={1}", file, line); File.WriteAllLines(@"C:\errorlines.log", errorlines); string[] ReadAllLines(string path); void WriteAllLines(string path, string[] contents); IEnumerable<string> EnumerateFiles(string path, string searchPattern); var errorlines = from file in Directory.EnumerateFiles(@"C:\logs", "*.log") from line in File.ReadLines(file) where line.StartsWith("Error:") select string.Format("File={0}, Line={1}", file, line); File.WriteAllLines(@"C:\errorlines.log", errorlines); Utilise toujours le minimum de mémoire quelque soit le nombre de fichiers / lignes / répertoires IEnumerable<string> ReadLines(string path); void WriteAllLines(string path, IEnumerable<string> contents);
BCL – Fichiers mappés en mémoire – 1/2 Scénario 1 Environment.SystemPageSize Gestion de la mémoire par le système Pagination automatique en mémoire Exploite la mémoire paginée du système Ressource partagée Gros Fichier Vue 1 Process 1 Vue 1 Vue N Vue N Vue 1 Vue 2 Vue N Scénario 2 Taille de la vue <= Mémoire disponible pour mapping (2Gb sur 32 bits) Mémoire partagée Simplification pour IPC (Inter-Process Communication) Stream (lecture séquentielle) Accessor (lecture aléatoire) Process 1 Process 2
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()); }
CodeContracts – 1/2 Permettre l’ajout de contrats dans le code Disponible dans 3.5 (installation séparée) 4 parties Une nouvelle API System.Diagnostics.Contracts Le « rewriter » (ccrewrite.exe) Injecte le code de vérification des contrats « aux bons endroits » Le « static checker » (cccheck.exe) Analyse le code pour vérifier si les contrats sont respectés Le générateur d’assembly (ccrefgen.exe) Produit une DLL avec les contrats seuls Static Checker : Team System uniquement Attention : 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
CodeContracts – 2/2 Contract.Requires Pré-condition Evalué « avant » l’appel Contract.Ensures Post-condition Evalué « après » l’appel Contract.OldValue Retourne la valeur avant l’appel ContractInvariantMethod Invariance de l’objet Appelé après chaque appel public public class CompteBancaire { private int numeroCompte, modulo; private double solde; public void EffectueDepot(double montant) Contract.Requires(montant > 0); Contract.Ensures(Contract.OldValue(this.solde) < this.solde); this.solde += montant; } static void Main() var compte = new CompteBancaire { numeroCompte = 0011234567, modulo = 27 }; compte.EffectueDepot(1000); public class CompteBancaire { private int numeroCompte, modulo; private double solde; public void EffectueDepot(double montant) Contract.Requires(montant > 0); Contract.Ensures(Contract.OldValue(this.solde) < this.solde); this.solde += montant; } [ContractInvariantMethod] private void ObjectInvariant() Contract.Invariant(this.solde >= 0); Contract.Invariant(this.numeroCompte % 97 == this.modulo); static void Main() var compte = new CompteBancaire { numeroCompte = 0011234567, modulo = 27 }; compte.EffectueDepot(1000); public class CompteBancaire { private int numeroCompte, modulo; private double solde; public void EffectueDepot(double montant) Contract.Requires(montant > 0); Contract.Ensures(ancien solde < nouveau solde); this.solde += montant; } static void Main() var compte = new CompteBancaire { numeroCompte = 0011234567, modulo = 27 }; compte.EffectueDepot(1000); public class CompteBancaire { private int numeroCompte, modulo; private double solde; public void EffectueDepot(double montant) this.solde += montant; } static void Main() var compte = new CompteBancaire { numeroCompte = 0011234567, modulo = 27 }; compte.EffectueDepot(1000); public class CompteBancaire { private int numeroCompte, modulo; private double solde; public void EffectueDepot(double montant) Contract.Requires(montant > 0); this.solde += montant; } static void Main() var compte = new CompteBancaire { numeroCompte = 0011234567, modulo = 27 }; compte.EffectueDepot(1000);
PFX – Parallel Framework Extensions static void Main() { IEnumerable<int> liste = Enumerable.Range(0, 10000000); var query = from i in liste where EstNombrePremier(i) select i; Console.WriteLine(query.Count()); } static bool EstNombrePremier(int p) int limite = (int)Math.Sqrt(p); for (int i = 2; i <= limite; i++) if (p % i == 0) return false; return true; .AsParallel() System.Collection.Concurrent BlockingCollection<T> ConcurrentQueue<T> ConcurrentDictionary<K, V> Lazy<T> System.Threading SemaphoreSlim ManuelResetEventSlim SpinLock Visual Studio Nouveau Debugger Nouveau Profiler 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) Parallel.Invoke(() => RealiseAction1(), () => RealiseAction2(), () => RealiseAction3());
System.Numerics – 1/2 Une nouvelle DLL : System.Numerics.dll BigInteger Un entier, « arbitrairement grand » Complex Structure pour représenter des nombres complexes
System.Numerics – 2/2 BigInteger static BigInteger Factorielle(BigInteger i) { if (i == 2) return 2; return i * Factorielle(--i); } static void Main() Console.WriteLine(Factorielle(5)); Console.WriteLine(Factorielle(10)); static BigInteger Factorielle(BigInteger i) { if (i == 2) return 2; return i * Factorielle(--i); } static void Main() Console.WriteLine(Factorielle(5)); static BigInteger Factorielle(BigInteger i) { if (i == 2) return 2; return i * Factorielle(--i); } static void Main() Console.WriteLine(Factorielle(5)); Console.WriteLine(Factorielle(10)); Console.WriteLine(Factorielle(55)); static BigInteger Factorielle(BigInteger i) { if (i == 2) return 2; return i * Factorielle(--i); } static void Main() Console.WriteLine(Factorielle(5)); Console.WriteLine(Factorielle(10)); Console.WriteLine(Factorielle(55)); Console.WriteLine(Factorielle(542)); Prévu pour .NET 3.5 Retardé pour problème de performance Toutes opérations de int Autres opérations (statiques) Abs DivRem GreatestCommonDivisor Remainder 120 3628800 12696403353658275925965100847566516959580321051449436762275840000000000000 1607535095378011891056328484225529595243838798499054994766025156939288169810835272449306354580237969682411561904659247352233869578500369085015849202525200 // 11 autres lignes de chiffres 27593805066916468242618448796850243328574235699250768859321062302677755711983880776617227228201878615112377392168960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 120 3628800 120 120 3628800 12696403353658275925965100847566516959580321051449436762275840000000000000
C# 4.0 Co & Contra Variance des génériques Paramètres nommés et optionnels Types dynamiques Interopérabilité COM Améliorations à la Base Class Library Conclusion
Conclusion – 1/2 & Framework 4.0 Nouveautés au niveau du langage Codage Simplifications d’écriture Amélioration des performances Design Interopérabilité simplifiée et homogénéisée « Design By Contracts » Framework de concurrence
Tout simplement une nouvelle révolution Conclusion – 2/2 Nouveautés au niveau de l’environnement Team Foundation Server se démocratise Nouveaux debuggers Modélisation UML Nouveautés au niveau des frameworks ASP.NET, MVC, AJAX 4.0, Sync Framework, F#… Et Après ? C# 5.0 (?) : « Compiler As A Service » TFS : baisse des contraintes, installable sur un poste client Tout simplement une nouvelle révolution
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