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!?
}
}
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 typesbyte
,byte
,short
,ushort
,uint
ouulong
, à 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 typeulong
, à condition que la valeur de expression-constante n'est pas négatif.
(Extrait de la spécification du langage C # version 3.0)
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.
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.
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!
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
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)
La conversion de int -> short peut entraîner la troncature des données. C'est pourquoi.