Developpez.com - Rubrique .NET

Le Club des Développeurs et IT Pro

Tutoriel : Tour d'horizon des nouveautés de C# 4.0

Par Jérôme Lambert

Le 2008-12-07 15:57:37, par Jérôme Lambert, Rédacteur
Bonjour à tous,

Je vous présente mon tout dernier article qui vous permettra de découvrir ce que la future version de C# nous réserve :

C'est lors de la Microsoft PDC 2008 (Professional Developer Conference) que Anders Hejlsberg - père spirituel de C# - a dévoilé le voile sur la prochaine version de son langage : C# 4.0.
Au cours de cet article, nous ferons un tour d'horizon des nouveautés qui nous attendent pour cette nouvelle version du langage.
Lien de l'article : http://jlambert.developpez.com/tutoriels/dotnet/nouveautescsharp4/

Bonne lecture à tous
  Discussion forum
11 commentaires
  • adiGuba
    Expert éminent sénior
    Très intérressant !

    Par contre, en tant que développeurs Java, certaines de ces fonctionnalités me font un peu frémir :

    • Les types dynamiques sont plutôt l'apanage des langages de script...
      Cela génère un code peu sécurisé (le compilateur ne peut plus faire aucune vérification).

      Si je comprend tout à fait l'intérêt d'intégrer cela dans le runtime pour mieux supporter les langages de script (ce sera d'ailleurs également le cas dans le bytecode Java 7 avec la JSR 292), j'emet quand même de gros doute quand à l'intérêt de cela dans un langage fortement typé comme C# !
    • Les paramètres nommés, qui impliquent que les noms des paramètres soit intégrés dans la signature de la méthode.

      La moindre modification sur un nom de paramètre pourrait alors casser du code existant


    Sinon en ce qui concerne les paramètres optionnels, je trouve cela plutôt utile en C++ : cela permet d'éviter de multiplier les définitions de méthodes :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public static void MaMethode(string s, int i, bool b)
    {
    	Console.WriteLine("s = {0}, i = {1}, b = {2}", s, i, b);
    }
    
    public static void MaMethode(string s, int i)
    {
    	MaMethode(s, i, false);
    }
    
    public static void MaMethode(string s)
    {
    	MaMethode(s, 10);
    }
    Par contre je n'ai pas trop d'expérience là dessus (très peu de C++), et je me demande si cela ne peut pas posé quelques petits conflit dans certain cas un peu tordu...

    Enfin en ce qui concerne la covariance/contravariance des génériques, je confirme que c'est très pratique pour écrire du code encore plus "générique", même si cela complique encore un peu le code

    a++
  • Pour les pramètres nommés et optionnels, ça va de paire avec le typage dynamique lorsqu'on fait de l'interrop pour accéder, par exemple, à des méthodes Excel/Word qui ont une étendue interminable de paramètres optionnels.

    Avec C# 3.0 et les versions précédentes, on est obligé de définir une valeur pour chacun des paramètres même si on en a rien à faire. Avec C# 4.0, ce sera bientôt un mauvais souvenir.
  • adiGuba
    Expert éminent sénior
    Je suis d'accord sur le fait que cela peut avoir un coté intéressant et utile

    Mais les types dynamiques reviennent à utiliser un typage faible dans un langage fortement typé

    Le cast est peut-être pas très joli, mais il a un intérêt : c'est comme un warning qui dit "attention je change le type", et qui signale donc un problème potentiel.
    Mais si l'opération réussi le reste du code est bien typesafe.

    Avec les types dynamiques le cast disparait mais c'est l'ensemble du code qui est potentiellement erroné !
    Le compilateur ne pourra pas signaler les éventuels problème sur un appel de méthode erroné

    a++
  • smyley
    Expert éminent
    Personnellement l'utilité principale que je vois aux types dynamiques c'est lorsque l'on se bat avec de la réflection. Par exemple, la ligne
    Code :
    1
    2
    3
    4
    5
    object obj = quelquechose;
    Type bidule = obj.GetType();
    MethodInfo m = bidule.GetMethod("Test",...)
    m.Invoke(obj, ...)
    deviendrais
    Code :
    1
    2
    3
    dynamic obj = quelquechose;
    obj.Test();
    Et donc histoires d'interop et autres on va vite sentir la différence. Par contre c'est sur c'est donner plus de pouvoirs aux développeurs et il faudra faire attention de ne pas l'utiliser n'importe comment.
  • On est d'accord qu'il va falloir utiliser le typage dynamique à bon escient, lorsque cela s'avère vraiment nécessaire (interrop, réflexion).

    D'ailleurs, Smyley l'a montré dans son exemple, la réflexion n'est pas type safe lorsqu'on joue avec des accès aux méthodes/propriétés/etc via des string. Si tu te trompes => exception.
  • adiGuba
    Expert éminent sénior
    Envoyé par Jérôme Lambert
    On est d'accord qu'il va falloir utiliser le typage dynamique à bon escient, lorsque cela s'avère vraiment nécessaire (interrop, réflexion).
    Perso je crains que ces types dynamiques ne soit privilégiés à d'autres solutions que je trouve plus propre.

    Si je reprend l'exemple de la réflection :
    Code :
    1
    2
    dynamic obj = quelquechose;
    obj.Test();
    Puisqu'on connait la signature de la méthode, pourquoi ne pas tout simplement faire ceci :
    Code :
    1
    2
    UnTypeCommun obj = (UnTypeCommun) quelquechose;
    obj.Test();
    De plus cela peut être complètement sécurisé via l'opérateur is (ou instanceof en Java) :
    Code :
    1
    2
    3
    4
    if (quelquechose is UnTypeCommun) {
    	UnTypeCommun obj = (UnTypeCommun) quelquechose;
    	obj.Test();
    }
    Dans tous les cas où on connait la méthode a appeler à la compilation, mais qu'on ignore le type de l'objet, je pense personnellement qu'il est préférable de passer par un cast sur le type réel ou un type parent commun.

    Envoyé par Jérôme Lambert
    D'ailleurs, Smyley l'a montré dans son exemple, la réflexion n'est pas type safe lorsqu'on joue avec des accès aux méthodes/propriétés/etc via des string. Si tu te trompes => exception.
    Oui... sauf que c'est propre à la réflection : on sait très bien que cela peut générer une exception. L'API de reflection est tout sauf sûr

    A l'inverse avec les types dynamiques, on se retrouve avec des codes apparemment anodins mais source de problème potentiel :
    Code :
    obj.Test();
    Un appel de méthode qui échoue ! (ce n'est pas le code de la méthode qui remonte une exception, mais bel et bien l'appel de la méthode). Le problème étant que l'exception peut survenir n'importe où !

    Ce n'est que mon avis, mais je ne trouve pas ce mélange de niveau de typage est à utiliser avec des pincettes...

    a++
  • smyley
    Expert éminent
    Envoyé par adiGuba

    Puisqu'on connait la signature de la méthode, pourquoi ne pas tout simplement faire ceci :
    Quand on utilise la reflexion c'est justement parce qu'on ne connais pas ce genre de chose, où que le type en question n'est pas connu à l'avance donc cela interdit toute tentative de cast. Et le 'is' existe aussi en C#.

    Envoyé par adiGuba

    Oui... sauf que c'est propre à la réflection : on sait très bien que cela peut générer une exception. L'API de reflection est tout sauf sûr
    Bah justement, ça risque de beaucoup servir pour faire de la reflexion, en écrivant moins un code équivalent (avec les mêmes potentiels d'exceptions).
    Même avec la réflexion on peut avoir un obj.Invoke qui échoue. Pour moi le obj.Test() est un invoke dissimulé, automatiquement généré par le compilateur (je sens que je vais aimer ).
    Dès qu'on sais ce que fait réellement cette méthode, on e cours pas plus de risque que de faire la même chose en 50 lignes à coups de réflexion ou autres.
  • A mon avis, ce qui gêne le plus adi c'est qu'il sera plus difficile de différencier un type classique, d'un type dynamique au milieu de centaines de lignes de code.
  • adiGuba
    Expert éminent sénior
    Envoyé par smyley
    Quand on utilise la reflexion c'est justement parce qu'on ne connais pas ce genre de chose, où que le type en question n'est pas connu à l'avance donc cela interdit toute tentative de cast. Et le 'is' existe aussi en C#.
    Je sais très bien pour le is j'ai logiquement posté du code C# (en Java on utilise instanceof)

    Ce que je veux dire, c'est que si on ne connait pas le type précis de l'objet, mais qu'on sait qu'il possède une certaine méthode, alors il serait plus propre de ramener cela à un type parent ou une interface décrivant la méthode en question.

    Perso j'évite d'utiliser la réflexion lorsque je connais à l'avance le nom de la méthode... et ma remarque va dans ce sens en fait

    Envoyé par smyley
    Même avec la réflexion on peut avoir un obj.Invoke qui échoue. Pour moi le obj.Test() est un invoke dissimulé, automatiquement généré par le compilateur (je sens que je vais aimer ).
    C'est justement ce qui me gène : l'invoke est dissimulé !
    Pour moi ce type d'invocation est propre aux langages de scripts...

    Envoyé par Jérôme Lambert
    A mon avis, ce qui gêne le plus adi c'est qu'il sera plus difficile de différencier un type classique, d'un type dynamique au milieu de centaines de lignes de code.
    Voilà c'est tout à fait cela !

    Alors qu'on avançait à grand pas vers du code plus sécurisé (comme les Generics qui permettent de sécuriser beaucoup de chose), j'ai presque l'impression que c'est un retour en arrière : n'importe quel code peut générer une erreur

    a++
  • Philippe Vialatte
    Expert éminent sénior

    Alors qu'on avançait à grand pas vers du code plus sécurisé (comme les Generics qui permettent de sécuriser beaucoup de chose), j'ai presque l'impression que c'est un retour en arrière : n'importe quel code peut générer une erreur
    Perso, je vois juste ca comme une option supplémentaire, ce n'est pas parce que techniquement on peut le faire qu'on doit le faire...sinon, je votes pour qu'on enleve les dataset fortement types, les sqldatasource et le mode design des pages webs (nyark )

    En particulier, je ne comptes pas m'en servir pour autre chose que l'interop...ou on en est au point ou les parties qui vont par exemple manipuler du word, sont faites en VB...pour eviter les
    Code :
    worddoc.SaveAs(ref destFile, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,ref missing, ref missing);


    En tout cas, je vais me lire ça bien tranquille de chez moi ce soir