En fait, le compilateur ne fait que détecter la violation de DirectCast s'il en déduit que la variable typée ne peut pas être convertie dans l'autre type.
Ce sont les équivalents réels :
double d = 10;
int i = (int)d;
Dim d As Double = 10
Dim i As Integer = d
Notez la dangerosité de cette construction. Si vous vous contentez d'assigner un double à un entier dans VB.NET, le double sera accidentellement réduit à un entier.
Alors que les programmeurs C# bénéficient de la sécurité au moment de la compilation de ne pas réduire accidentellement la taille d'une variable en .NET. Les programmeurs VB.NET doivent se contenter de toujours utiliser DirectCast comme une habitude de programmation sûre.
Ce sont les équivalents réels :
// Will not compile, cannot convert double to int
double d = 10;
int i = d;
' Will not compile, cannot convert double to int
Dim d As Double = 10
Dim i As Integer = DirectCast(d, Integer)
Concernant Commentaire de Dan Tao :
Il n'est pas nécessaire d'utiliser DirectCast en C#. Le runtime empêche également le chargement d'une valeur longue en valeur entière. C'est ce que l'OP prétend, que C# n'a pas DirectCast, que DirectCast peut empêcher l'assignation de différents types de variables, alors que "parce que" C# n'a pas ce DirectCast, il se trompe silencieusement lors de l'assignation de différents types. Mais comme vous pouvez le voir, ce n'est pas le cas. Le casting de C# est exactement la même chose que DirectCast. Cela provoquera un InvalidCastException erreur d'exécution :
long l = 10;
object o = l;
int i = (int)o;
Cela provoquera également le même erreur d'exécution comme ci-dessus :
Dim l As Long = 10
Dim o As Object = l
Dim i As Integer = DirectCast(o, Integer)
C'est là que la partie "amusante" entre en jeu. Avec VB.NET, vous devez vous souvenir de nombreux mots-clés pour accomplir quelque chose. En C#, si un mot-clé donné peut être utilisé dans un autre scénario (comme ici le downcasting de variable), ils n'inventeront pas un autre mot-clé juste pour le faire.
En C#, il suffit de faire cela :
long l = 10;
object o = l;
int i = (int)(long)o;
En VB.NET, si vous voulez vraiment déclasser la variable, et que vous voulez le faire de manière orthogonale, c'est-à-dire en vous souvenant d'un seul mot-clé, vous devez faire ceci :
Dim l As Long = 10
Dim o As Object = l
Dim i As Integer = DirectCast(DirectCast(o, Long), Integer)
Mais cela ne compilera pas, alors comment pouvons-nous réaliser le downcasting de long en integer ? Vous devez vous souvenir des autres mots-clés de VB.NET. Alors qu'en C#, c'est orthogonal, vous décomposez une variable en utilisant cette construction (typehere)
vous pouvez aussi faire du downcast/upcast en utilisant la même construction. (typehere)
. En VB.NET, il y a une déconnexion fondamentale entre le chargement d'une valeur à partir d'un objet et son downcasting. Donc, en VB.NET, vous devez faire ceci :
Dim l As Long = 10
Dim o As Object = l
Dim i As Integer = CType(o, Integer)
Hmm Je pense que la confusion de l'OP provient de l'utilisation multiple en C# de la fonction (typehere)
. Premièrement, il est utilisé pour le downcasting ; deuxièmement, la même construction (voir la première partie de ce post, object o = l
) est également utilisé pour l'unboxing de la valeur de l'objet, qui, rassurez-vous, a le comportement de conversion de type sûr de DirectCast. Ils sont les mêmes !
Cette baisse de régime...
long l = 1;
int i = (int) l;
...n'est pas équivalent à :
Dim l As Long = 1
Dim i As Integer = DirectCast(l, Integer)
Si vous voulez faire du downcasting, vous devez faire ça :
Dim l As Long = 1
Dim i As Integer = CInt(l) ' Can also use CType
Maintenant, si un programmeur VB.NET programme par intention, et ne s'endort pas en codant, pourquoi utilisera-t-il DirectCast alors qu'il sait parfaitement qu'il ne peut pas assigner des types différents ? Si le programmeur VB.NET voulait vraiment faire du downcast, il n'aurait pas dû essayer DirectCast en premier lieu. Maintenant, le programmeur VB.NET, en découvrant que DirectCast ne peut pas être utilisé pour le downcasting, doit revenir en arrière et remplacer ce qu'il a écrit par CInt (ou CType).
11 votes
+1 pour définir les mots-clés et ne pas obliger les gens à les chercher.
4 votes
string s = "10"; int i = (int)s;
ne compile pas en C#.0 votes
Avez-vous essayé d'utiliser reflector pour comparer le MSIL ?
0 votes
@Robert : Oups ! J'ai réécrit avec le double... et j'ai effectivement fait passer mon code par des compilateurs cette fois :)
0 votes
@Robert Davis : Je pense que Collin Suave n'essaie pas d'exécuter dans Visual Studio ses hypothèses
3 votes
@csauve : Vous vous trompez sur l'utilité des mots-clés. Alors que
int i = (int)d;
peut effectuer une conversion connue pour un type connu comme dans votre exemple de code, dans n'importe quel scénario où vous de manière réaliste utiliceDirectCast
en VB.NET (c'est-à-dire lorsque le type d'un objet n'est pas connu au moment de la compilation), le casting avec()
en C# fait no effectuer une conversion -- il juste plâtres. Ainsi, un double boxé ne peut pas être déboxé en tant qu'entier. Pour cette raison, les deux sont effectivement équivalents.0 votes
@csauve : Dans l'exemple que vous donnez, DirectCast est un une fausse couverture de sécurité c'est-à-dire ne sont pas portés tout le temps . Tout d'abord, si vous avez vraiment besoin de convertir votre variable en une autre type compatible DirectCast n'est d'aucune utilité. Voir mon post ici : stackoverflow.com/questions/2683847/
0 votes
Je pense que vous pourriez être intéressé par le
System.Type
méthodeIsAssignableFrom
.1 votes
Par curiosité, pourquoi besoin de ça ?
1 votes
Vos déclarations sur la façon dont
()
est différent deDirectCast
sont correctes pour valeur mais incorrecte pour les types référence types. (Les deux sont équivalents pour les types de référence ; aucune conversion n'est effectuée), ce qui en fait une comparaison inutile, car, à mon avis, il n'y a aucune raison d'utiliserDirectCast
con un valeur type. La façon dont je le vois :()
est équivalent àCType
pour les types de valeurs, et àDirectCast
pour les types de référence.