IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Casse-têtes en C#
Un article de Jon Skeet sur les pièges du langage, traduit par Jean-Michel Ormes

Le , par Jean-Michel Ormes

38PARTAGES

4  0 
Cette discussion est destinée à recueillir vos commentaires sur l'article Casse-têtes en C# (traduction de l'article C# Brainteasers de Jon Skeet)


Régulièrement, je tombe sur une situation intéressante en C# qui donne des résultats surprenants. Cette page contient une liste d'exemples. Dans les exemples où il n'y a qu'un bout de code, nous supposerons que celui-ci est dans la méthode Main. Afin de ne pas tomber accidentellement sur les résultats avant que vous ne le souhaitiez, j'ai mis les réponses sur une autre page.

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de antoine.debyser
Membre confirmé https://www.developpez.com
Le 28/03/2012 à 9:15
Bonjour,

C'est chouette que vous traduisiez les articles de John Skeet, ils sont souvent très pertinents.

Par contre une petite erreur s'est glissé dans la traduction au niveau des réponses. Concernant la dernière devinette
mais à ce stade, c'est effectivement un choix entre string x et params string [] x.
devrait etre
mais à ce stade, c'est effectivement un choix entre object x et params string [] x.
0  0 
Avatar de Jean-Michel Ormes
Rédacteur https://www.developpez.com
Le 29/03/2012 à 6:47
Merci, j'ai pris en compte ta correction
0  0 
Avatar de morgand
Membre averti https://www.developpez.com
Le 29/03/2012 à 10:04
Bonjour,

je me pose une question très précise sur le problème "Print, Print, Print ..."
je comprend pourquoi le 10*10, ma question porte sur la déclaration de "i".

Elle est déclaré dans le For, et normalement on ne peut plus l'utilisé en dehors du For.
Exemple :
Code : Sélectionner tout
1
2
3
4
5
6
for (int i=0; i < 10; i++)
{
      printers.Add(delegate { Console.WriteLine(i); });
}
Console.WriteLine(i);
Ce code est impossible.
Alors comment on peut l'utiliser dans la boucle du dessous ? J'aimerai comprendre le fonctionnement de la CLR derrière.
0  0 
Avatar de Sehnsucht
Membre chevronné https://www.developpez.com
Le 29/03/2012 à 10:19
Bonjour,

C'est expliqué sur le lien variables capturées juste en dessus de l'exemple
Does the variable even exist outside MakeDelegate? Well, the answer is yes - because the compiler compiles it into an instance variable in a new type behind the scenes. If you compile the above and look at it with ildasm, you'll see that there actually isn't a Random local variable in MakeDelegate at all, as far as the runtime is concerned! Instead, there's a local variable of a nested type with some compiler-generated name (the time I compiled it, the name was <>c__DisplayClass1).
Ou en français dans le texte, une classe est générée et stocke ces captures dans des champs qui sont initialisés dans son constructeur par les valeurs locales (et donc non perdues lors de la sortie de la portée du bloc).

Enfin quelqu'un l'expliquera sans doute mieux que moi

Cordialement !
0  0 
Avatar de morgand
Membre averti https://www.developpez.com
Le 29/03/2012 à 10:25
Merci c'est l'explication que j'attendai
Je n'avais jamais eu le détail du fonctionnement
0  0 
Avatar de Noze_
Futur Membre du Club https://www.developpez.com
Le 12/04/2012 à 15:02
Une petite remarque concernant ce code :

Code : Sélectionner tout
1
2
3
4
  
double d1 = 1.000001;
double d2 = 0.000001;
Console.WriteLine((d1-d2)==1.0);
Le compilateur verra que le résultat diffère, avec en sortie "False".
Cependant, en modifiant légèrement ce bout de code

Code : Sélectionner tout
1
2
3
4
  
double d1 = 1.0000001;
double d2 = 0.0000001;
Console.WriteLine((d1-d2)==1.0);
On obtiendra bien "True" en sortie.

Que peut-on en déduire ?
0  0 
Avatar de Tryp'
Membre du Club https://www.developpez.com
Le 16/04/2012 à 15:29
Citation Envoyé par Noze_ Voir le message
Une petite remarque concernant ce code :

Code : Sélectionner tout
1
2
3
4
  
double d1 = 1.000001;
double d2 = 0.000001;
Console.WriteLine((d1-d2)==1.0);
Le compilateur verra que le résultat diffère, avec en sortie "False".
Cependant, en modifiant légèrement ce bout de code

Code : Sélectionner tout
1
2
3
4
  
double d1 = 1.0000001;
double d2 = 0.0000001;
Console.WriteLine((d1-d2)==1.0);
On obtiendra bien "True" en sortie.

Que peut-on en déduire ?
C'est une histoire de stockage des nombres flottants en binaire.

Un nombre entier est représenté par des 0 ou des 1, et, de droite à gauche, un bit à 1 a une valeur de 2^n (où n est sa position à partir de la droite).

Par exemple :
1101, de droite à gauche :
1 * 2^0 = 1
0 * 2^1 = 0
1 * 2^2 = 4
1 * 2^3 = 8
Donc 1101 en binaire vaut : 1 + 4 + 8 = 13

Pour la partie décimale, c'est presque pareil de gauche à droite. Sauf que cette fois ci, on utilise les puissances négatives de 2.

0.011, de gauche à droite (on oublie la partie entière) :
0 * 2^-1 = 0
1 * 2^-2 = 0.25
1 * 2^-3 = 0.125
Donc 0.011 en binaire vaut : 0.25 + 0.125 = 0.325

Pour répondre donc à ta question, il arrive que certains nombres ne peuvent pas être représentés correctement sur 32 bits (ou 64 bits), d'où la présence de certaines incohérences comme celle-ci. Il n'y a juste pas assez de bits disponibles pour cela. Tout est histoire de puissance de 2.

En espérant avoir été clair !
0  0