Différence entre DirectCast () et CType () dans VB.NET

99

Je suis un programmeur C / C ++ / C # expérimenté qui vient tout juste d'entrer dans VB.NET. J'utilise généralement CType (et CInt, CBool, CStr) pour les casts car il y a moins de caractères et c'était la première façon de diffuser à laquelle j'ai été exposé, mais je connais également DirectCast et TryCast.

Simplement, y a-t-il des différences (effet de distribution, performances, etc.) entre DirectCast et CType? Je comprends l'idée de TryCast.

Caleb Hearth
la source
6
Copie exacte de ce casting DataTypes avec DirectCast, CType, TryCast stackoverflow.com/questions/2703585/...
MarkJ

Réponses:

182

La première chose à noter est que VB.NET n'a pas d'analogue direct au (type)instancemécanisme de conversion de C # . J'évoque cela parce que c'est utile comme point de départ pour comparer les deux opérateurs VB.NET (et ce sont des opérateurs, pas des fonctions, même s'ils ont une sémantique de fonction).

DirectCast()est plus strict que l'opérateur de conversion C #. Il ne vous permet de lancer que lorsque l'élément en cours de diffusion est déjà du type vers lequel vous lancez le casting. Je pense que cela déballera toujours les types de valeur, mais sinon, il ne fera aucune conversion. Ainsi, par exemple, vous ne pouvez pas effectuer de cast de shortvers int, comme vous le feriez avec un (int)cast C # . Mais vous pouvez effectuer un cast de an IEnumerablevers un tableau, si votre IEnumerablevariable objet sous-jacente est vraiment un Array. Et bien sûr, vous pouvez effectuer un cast de Objectvers n'importe quoi, en supposant que le type de votre instance d'objet se trouve vraiment quelque part en dessous de votre type de distribution dans l'arborescence d'héritage.

C'est souhaitable car c'est beaucoup plus rapide . Il y a moins de conversion et de vérification de type à effectuer.

CType()est moins strict que l'opérateur de conversion C #. Il fera des choses que vous ne pouvez tout simplement pas faire avec un (int)cast de style simple , comme convertir une chaîne en entier. Il a autant de puissance que d'appeler Convert.To___()en C #, où ___est le type de cible de votre distribution.

C'est souhaitable car c'est très puissant. Cependant, cette puissance se fait au détriment des performances; ce n'est pas aussi rapide que DirectCast()ou l'opérateur de cast de C # car il peut avoir besoin de beaucoup de travail pour terminer le casting. En général, vous devriez préférer DirectCast()quand vous le pouvez.

Enfin, vous avez manqué un opérateur de casting:, TryCast()qui est un analogue direct à l' asopérateur C # .

Joel Coehoorn
la source
23
+1 Je dirais que la rigueur DirectCastest un autre avantage. Si vous faites une erreur, le compilateur vous le dit immédiatement, mais avec CTypeune erreur, cela pourrait provoquer un mauvais comportement occasionnel au moment de l'exécution - peut-être sur une machine utilisateur avec des paramètres régionaux différents.
MarkJ
1
Très bonne réponse. Donc , par ordre de complexité (petite à grande): DirectCast, TryCast, CType/ Convert.ToXYZ(), C<xyz>()serait correct?
devise du
3
@motto - fermer. Les "fonctions" C <xyz> () doivent être déplacées plus haut dans la liste, car ce sont en réalité des opérateurs plutôt que des fonctions, même si elles ont une sémantique de fonction. Pour les types qui les ont, ils sont très proches du casting (type) de C #, mais feront juste un peu plus de travail.
Joel Coehoorn
3
@MarkJ +1 pour votre commentaire, mais la note DirectCastn'est stricte qu'avec les classes, pas les interfaces (car vous pouvez avoir des types COM - et peut-être d'autres - qui implémentent en fait des interfaces non définies par la .GetInterfacesliste des types .NET ).
Mark Hurd
2
@JoelCoehoorn +1, mais en fait, TryCast()et asne sont pas exactement les mêmes. TryCast()fonctionne uniquement avec les types de référence, tandis que asfonctionne avec tout ce qui peut être nul. Cela int? icast = myNum as int?;fonctionnera très bien, mais Dim icast as Integer? = TryCast(myNum, Integer?)donnera une erreur de compilation. Encore une différence particulière entre les deux langues. lol
CptRobby
12

Avec CTypevous pouvez écrire quelque chose comme ça Ctype("string",Integer). Mais avec DirectCastl'instruction ci-dessus, cela donnerait une erreur de compilation.

 Dim a As Integer = DirectCast("1", Integer) 'Gives compiler error
 Dim b As Integer = CType("1", Integer) 'Will compile
Abhay
la source
0

DirectCastest plus restrictif que CType.

Par exemple, cela générera une erreur:

Sub Main()
    Dim newint As Integer = DirectCast(3345.34, Integer)
    Console.WriteLine(newint)
    Console.ReadLine()
End Sub

Il sera également affiché dans l'IDE de Visual Studio.

Cependant, cela ne génère pas d'erreur:

Sub Main()
    Dim newint As Integer = CType(3345.34, Integer)
    Console.WriteLine(newint)
    Console.ReadLine()
End Sub
Hemantha
la source