40 votes

Pourquoi êtes à court de valeurs null converti en int des valeurs null pour les comparant avec la valeur null?

Quand je compare les valeurs null valeurs courtes, le compilateur convertit tout d'abord en entier pour faire une comparaison avec la valeur null. Par exemple, considérons ce simple code:

short? cTestA;
if (cTestA == null) { ... }

Il est converti par le compilateur:

short? CS$0$0001 = cTestA;
int? CS$0$0002 = CS$0$0001.HasValue ? new int?(CS$0$0001.GetValueOrDefault()) : null;
if (!CS$0$0002.HasValue){ ... }

Cela se produit pour tous .NET des versions, y compris .NET 4.

Ce qui me manque ici? Quelle est la raison de cette double conversion juste pour un HasValue vérifier?

Suivi

Ce que j'attends le compilateur à faire est de faire une vérification simple avec .HasValue, if (cTestA.HasValue){}. Au moins ce est ce que je fais dans mon code après je découvre cette conversion.

Pourquoi est-ce que ce code supplémentaire ajouté pour un test simple?

37voto

Eric Lippert Points 300275

Re: votre dernière mise à jour:

C'est un bug dans le nullable arithmétique de l'optimiseur.

Le nullable optimiseur de supprimer l'inutile conversion en int? lorsque vous faites quelque chose comme:

short? s = null;
int? x = s + 1;

Le unoptimized codegen ne l'équivalent de:

short? s = null;
int? x;
int? temp = s.HasValue ? new int?((int)s.Value) : new int?();
x = temp.HasValue ? new int?(x.Value + 1) : new int?();

L'optimisation de la codegen ne l'équivalent de:

short? s = null;
int? x;
x = s.HasValue ? new int?((int)s.Value + 1) : new int?();

Cependant, l'optimiseur de requête contient un bogue; nous ne retirez pas la conversion inutile pour l'égalité.

Merci de le signaler à mon attention; nous allons le corriger pour Roslyn. En fait, je suis sur le point d'écrire la nullable optimizer pour Roslyn, dans les deux prochaines semaines.

Mise à JOUR: j'ai écrit que l'optimiseur, et si vous êtes intéressé par la façon dont il fonctionne, j'ai écrit une série d'articles sur elle, qui commence ici:

http://ericlippert.com/2012/12/20/nullable-micro-optimizations-part-one/

29voto

Anthony Pegram Points 58528

Voir la section 4.1.5 du C# 4.0 spécification du langage. En particulier, de l'intérêt:

C# supporte les neuf types intégraux: sbyte, byte, short, ushort, int, uint, long, ulong, et l'omble chevalier. [omis texte]

L'intégrale de type les opérateurs unaires et binaires fonctionnent toujours avec une signé de 32 bits non signé de 32 bits, 64 bits signé ou la précision de 64 bits non signé de précision:

  • [omis des points de balle]

  • Pour le binaire +, –, *, /, %, &, ^, |, ==, !=, >, <, >=, et <= les opérateurs, les opérandes sont convertis en type T, où T est le premier de type int, uint, long, et ulong que peut bien représenter tous les possibles les valeurs des deux opérandes. L'opération est ensuite effectuée en utilisant les la précision de type T, et le type de résultat est T (ou bool pour l' opérateurs relationnels). Il n'est pas permis pour un opérande de de type long et de l'autre pour être de type ulong avec les opérateurs binaires.

Opérations à l'aide de courts sont promus en int, et ces opérations sont levées pour leur nullable homologues. (Ce qui conduit à des sections 7.3.6.2 et 7.3.7)


Ok, c'est par la Conception, mais ne comprends toujours pas pourquoi ils font ça, ils ont d'optimiser la chaîne ajoute trop, pourquoi la gauche les chiffres à eux seuls et ajouter plus de code pour cette simple comparaison

C'est simplement la manière dont le langage est conçu, avec une considération pour les optimisations dans l'architecture moderne. Pas spécifiquement dans ce contexte, mais estiment que les paroles de Eric Lippert comme indiqué ici

L'arithmétique n'est jamais fait en short en C#. L'arithmétique peut être fait dans les entiers, les nombres uint compris, longs et ulongs, mais l'arithmétique n'est plus à faire en short. Short de promouvoir l'int et le calcul est fait en ints, parce que, comme je l'ai dit avant, la grande majorité des calculs arithmétiques de s'insérer dans un int. La grande majorité ne rentre pas dans un court. Court arithmétique est peut-être plus lente sur du matériel moderne, qui est optimisé pour les entiers, et court arithmétique ne pas prendre moins de place, ça va être fait dans les ints ou longs sur la puce.


Votre dernière mise à jour:

Ce que j'attends le compilateur à faire est de faire une vérification simple avec .HasValue if (cTestA.HasValue){} au moins ce est ce que je fais sur mon code après je découvre cette conversion. C'est donc ce que je ne comprends vraiment pas pourquoi ne pas faire simple pense, mais tout ajouter ce code supplémentaire. Le compilateur essaie toujours d'optimiser le code - pourquoi ici d'éviter que simple .HasValue vérifier. Il me manque quelque chose ici pour vous...

Je vais avoir à s'en remettre à un compilateur expert pour dire pourquoi ils choisissent d'aller pour la conversion à la place de l'immédiat HasValue vérifier, sauf à dire qu'il pourrait être simplement un ordre des opérations. La spécification du langage dit opérateur binaire opérandes sont promus, et c'est ce qu'ils ont fait dans l'extrait de code. La spécification du langage se passe pour le dire plus tard que les vérifications x == null, où x est une valeur de type nullable, peuvent être convertis en !x.HasValue, et c'est aussi ce qu'ils ont fait. Dans le code compilé vous avez présenté, le numérique, la promotion a simplement pris la priorité sur la nullable comportement.

Comme pour le compilateur toujours essayer d'optimiser le code, à nouveau, un expert peut préciser, mais ce n'est pas le cas. Il y a des optimisations qu'il peut faire et d'autres, il s'en remet donc à peut-être la gigue. Il y a des optimisations que soit le compilateur ou le scintillement peut ou ne peut pas faire, selon qu'on est un débogage et la libération de construire, avec ou sans un débogueur. Et sans doute il y a des optimisations qu'ils pouvaient faire ce qu'ils simplement choisir de ne pas, parce que les coûts et les avantages de ne pas jouer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X