Quizz C#. Vous croyez connaître le langage ? et bien regardez ce qui suit !

C# est un langage merveilleux, plein de charme... et de surprises !

En effet, s'écartant des chemins battus et intégrant de nombreuses extensions comme Linq aujourd'hui ou les méthodes anonymes hier, il est en perpétuelle évolution. Mais ces "extensions" transforment progressivement un langage déjà subtile à la base (plus qu'il n'y paraît) en une jungle où le chemin le plus court n'est pas celui que les explorateurs que nous sommes auraient envisagé...

Pour se le prouver, 6 quizz qui vous empêcheront de bronzer idiot ou de vous endormir au boulot !

Un petit projet exemple avec les questions et les réponses sera téléchargeable en fin d'article demain...
[EDIT 4-7-08] Le lien se trouve désormais en fin d'article. Le code source contient les réponses au quizz.

Quizz 1

Etant données les déclarations suivantes :

class ClasseDeBase
{
   
public virtual void FaitUnTruc(int x)
    {
Console.WriteLine("Base.FaitUnTruc(int)"); }
}

class ClasseDérivée : ClasseDeBase
{
   
public override void FaitUnTruc(int x)
   { Console.WriteLine("Dérivée.FaitUnTruc(int)"); }

   public void FaitUnTruc(object o)
  {
Console.WriteLine("Dérivée.FaitUnTruc(object)"); }
}

Pouvez-vous prédire l'affiche du code suivant et expliquer la sortie réelle :

    ClasseDérivée d = new ClasseDérivée();
    int i = 10;
    d.FaitUnTruc(i);

Gratt' Gratt' Gratt'.....

Quizz 2

Pouvez-vous prédire l'affichage de cette séquence et expliquer l'affichage réel ?

double d1a = 1.00001;
double d2a = 0.00001;
Console.WriteLine((d1a - d2a) == 1.0);

double d1b = 1.000001;
double d2b = 0.000001;
Console.WriteLine((d1b - d2b) == 1.0);

double d1c = 1.0000001;
double d2c = 0.0000001;
Console.WriteLine((d1c - d2c) == 1.0);

Je vous laisse réfléchir ...

Quizz 3

Toujours le même jeu : prédire ce qui va être affiché et expliquer ce qui est affiché réellement... c'est forcément pas la même chose sinon le quizz n'existerait pas :-)

List<Travail> travaux = new List<Travail>();
Console.WriteLine("Init de la liste de delegates");
for (int i = 0; i < 10; i++)
{ travaux.Add(
delegate { Console.WriteLine(i); }); }

Console.WriteLine("Activation de chaque delegate de la liste");

foreach (Travail travail in travaux) travail();

 Les apparences sont trompeuses, méfiez-vous !

Quizz 4

Ce code compile-t-il ?

public enum EtatMoteur { Marche, Arrêt }

public static void DoQuizz()
{
   
EtatMoteur etat = 0.0;
   
Console.WriteLine(etat);
}

Quizz 5

 Etant données les déclarations suivantes :

private static void Affiche(object o)
{
Console.WriteLine("affichage <object>"); }

private static void Affiche<T>(params T[] items)
{
Console.WriteLine("Affichage de <params T[]>"); }

 Pouvez-vous prédire et expliquer la sortie de l'appel suivant :

  Affiche("Qui va m'afficher ?");

 Je sens que ça chauffe :-)

Quizz 6

 Etant données les déclarations suivantes :

 delegate void FaitLeBoulot(); private static FaitLeBoulot FabriqueLeDélégué()
{
  
Random r = new Random();
  
Console.WriteLine("Fabrique. r = "+r.GetHashCode());

  
return delegate {
                           
Console.WriteLine(r.Next());
                           
Console.WriteLine("delegate. r = "+r.GetHashCode());
                         };

}

 Quelle sera la sortie de la séquence suivante :

    FaitLeBoulot action = FabriqueLeDélégué();
    action();
   
action();

 

Conclusion

C# est un langage d'une grande souplesse et d'une grande richesse. Peut-être qu'à devenir trop subtile il peut en devenir dangereux, comme C++ était dangereux car trop permissif.

Avec C#, même de très bons développeurs peuvent restés interloqués par la sortie réelle d'une séquence qui n'a pourtant pas l'air si compliquée.
Ses avantages sont tels qu'il mérite l'effort de compréhension supplémentaire pour le maîtriser réellement, mais tout développeur C# (les moyens comme ceux qui pensent être très bons!) doit être mis au moins une fois dans sa vie face à un tel quizz afin de lui faire toucher la faiblesse de son savoir et les risques qu'il prend à coder sans vraiment connaître le langage.

Comme toujours l'intelligence est ce bel outil qui nous permet de mesurer à quel point nous ne savons rien.
Nous sommes plutôt habitués à envisager cette question sous un angle métaphysique, le développement nous surprend lorsque lui aussi nous place face à cette réalité...

Pour le projet exemple dont le source contient les réponses cliquez sur le lien en fin de billet.

So (et plus que jamais!) .. Stay Tuned !

Quizz.rar (103,41 kb)


Tags: Categories: C# | Framework .NET

Thu 03 Jul 2008 06:14 2 Comments
Actions: E-mail | Permalink | Comment RSSRSS comment feed

Comments

July 10. 2008 09:35

seb.49

Pour le quizz 2, la solution est elle de toujours utiliser les arrondis quand on utilise double ou decimal

ex : Console.WriteLine(Math.Round((d1b - d2b),1) == 1.0); //Donne true

Merci pour ces exercices en tout cas.

seb.49

July 10. 2008 11:20

Olivier

Ce problème des décimaux se pose depuis longtemps, bien avant C#, c'est aussi un classique avec les bases de données. Il n'y a pas forcément de solution miracle applicable à toutes les situations.
La première chose qu'il faut se demander c'est pourquoi utiliser des décimaux... S'il s'agit d'une application manipulant des données exactes (monétaires, données physiques..) on a souvent intérêt à préférer les entiers, quitte à les afficher avec un diviseur (par 100 pour avoir 2 décimales, etc..).
Le sens des chiffres est essentiel, c'est ce qu'on tente d'apprendre aux élèves en classe de physique : donner des résultats sur 8 décimales alors que les données originales n'ont de sens que sur 2 par exemple... 2.5 divisé par 3 vaut mathématiquement 0,8333333333333333.. mais en physique et donc dans la réalité pour écrire le résultat encore faut-il connaître l'incertidute entachant les mesures 2.5 et 3 ! Si elle est de 0,1, cela signifie que 2.5 est en réalité une valeur comprise entre 2.4 et 2.6 et que 3 est une valeur entre 2.9 et 3.1, exprimer le résultat de 2.5/3 autrement que sous la forme 0.8 n'a guère de sens donc... et donc peu importe la valeur des décimales qui suivent, elles ne sont pas significatives (le résultat réel se situe entre 0.774.. et 0.896.., donc 0.8 avec une incertitude de 0.1).
Pour revenir plus prosaïquement au développement, l'erreur n'est donc pas tant dans l'inexactitude du test C# mais dans la mauvaise manipulation des chiffres significatifs qui est faite par le développeur. Aucun résultat manipulé par une application réelle travaillant sur des données réelles ne peut fournir un résultat de calcul infiniment précis, il y a forcément une limite, celle de l'incertitude entachant chaque nombre original et c'est cette incertitude que doit refléter l'éventuelle utilisation de Round ou autre méthode de troncature.
On termine ainsi par découvrir une faiblesse de l'analyse de l'application (quelle est l'incertitudes des mesures ?), une faiblesse du développeur (qui a oublié ses cours de physiques !) plutôt qu'un défaut du langage ! Le test d'égalité montré dans l'article ne veut en réalité absolument rien dire du tout ! Alors que C# renvoie true ou false, peu importe en fait ! C'est ailleurs que se trouve le problème.
Dans la pratique le résultat sera tronqué ou arrondi avec un nombre de décimales dépendant de l'incertitude des données de base. Pour mettre en oeuvre tout cela, on aura même intérêt à écrire sa propre classe de type "decimal" dont les opérateurs comme equal seront écrits en tenant compte de l'incertitude. Pour les cas plus simples ou une telle rigueur n'est pas forcément requise, on peut aussi créer un class helper qui ajoute une méthode de type EstEgalAvecIncertitude à la classe decimal et qui accèpte en paramètre le nombre de décimales significatives. On obtient alors un appel du type : "if (leNombre.EstEgalAvecIncertitude(unAutreNombre,lesDecimalesSignificatives)) ..."
Sous le couvert d'un simple problème de langage, on découvre une problématique bien plus complexe. J'aime bien les exemples de ce type qui permettent d'aborder des sujets rarement évoqués et pourtant essentiels ! Smile Et je vous remercie par ailleurs de votre commentaire qui m'a donné l'occasion de pouvoir ainsi digresser Smile

Olivier

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading