web-dev-qa-db-fra.com

Pourquoi puis-je passer 1 comme court, mais pas la variable int i?

Pourquoi la première et la deuxième écriture fonctionnent-elles mais pas la dernière? Existe-t-il un moyen de les autoriser tous les 3 et de détecter si c'était 1, (int) 1 ou si je suis passé? Et vraiment pourquoi est-on autorisé mais le dernier? Le deuxième étant autorisé mais pas le dernier me fait vraiment peur.

Démo pour montrer l'erreur de compilation

using System;
class Program
{
    public static void Write(short v) { }
    static void Main(string[] args)
    {
        Write(1);//ok
        Write((int)1);//ok
        int i=1;
        Write(i);//error!?
    }
}
146
user34537

Les deux premiers sont des expressions constantes, le dernier ne l'est pas.

La spécification C # permet une conversion implicite de int en short pour les constantes, mais pas pour les autres expressions. C'est une règle raisonnable, car pour les constantes, le compilateur peut s'assurer que la valeur correspond au type cible, mais pas pour les expressions normales.

Cette règle est conforme à la directive selon laquelle les conversions implicites doivent être sans perte.

6.1.8 Conversions implicites d'expression constante

Une conversion d'expression constante implicite permet les conversions suivantes:

  • Une expression constante (§7.18) de type int peut être convertie en type sbyte, byte, short, ushort, uint ou ulong, à condition que la valeur de l'expression constante se situe dans la plage du type de destination.
  • Une expression constante de type long peut être convertie en type ulong, à condition que la valeur de expression-constante n'est pas négatif.

(Extrait de la spécification du langage C # version 3.0)

186
CodesInChaos

Il n'y a pas de conversion implicite de int vers short en raison de la possibilité de troncature. Cependant, un expression constante peut être traité comme étant du type cible par le compilateur.

1? Pas de problème: c'est clairement une valeur short valide. i? Pas tant que ça - ça pourrait être une valeur> short.MaxValue par exemple, et le compilateur ne peut pas vérifier cela dans le cas général.

67
Konrad Rudolph

un int littéral peut être implicitement converti en short . Tandis que:

Vous ne pouvez pas convertir implicitement des types numériques non littéraux de plus grande taille de stockage en short

Ainsi, les deux premiers fonctionnent car la conversion implicite des littéraux est autorisée.

8

Je crois que c'est parce que vous passez un littéral/constant dans les deux premiers, mais il n'y a pas de conversion de type automatique lors du passage d'un entier dans le troisième.

Edit: Quelqu'un m'a battu pour ça!

6
Justin

Parce qu'il n'y aura pas de conversion implicite entre type non littéral en short de plus grande taille.

La conversion implicite n'est possible que pour l'expression constante.

public static void Write(short v) { }

Où au fur et à mesure que vous passez integer valeur comme argument à short

int i=1;
Write(i);  //Which is Nonliteral here
3
Vishal Suthar

Le compilateur a dit pourquoi le code échoue:

cannot convert `int' expression to type `short'

Voici donc la question que vous devriez vous poser: pourquoi cette conversion échoue-t-elle? J'ai googlé "c # convert int short" et je me suis retrouvé sur la page MS C # pour le mot clé short:

http://msdn.Microsoft.com/en-us/library/ybs77ex4 (v = vs.71) .aspx

Comme le dit cette page, les conversions implicites d'un type de données plus grand vers short ne sont autorisées que pour les littéraux. Le compilateur peut savoir quand un littéral est hors plage, mais pas autrement, il a donc besoin d'être rassuré que vous avez évité une erreur hors plage dans votre logique de programme. Cette assurance est fournie par un casting.

Write((short)i)
3
Isaac Rabinovitch

La conversion de int -> short peut entraîner la troncature des données. C'est pourquoi.

0
ak1238