C # fournit le ref
et le out
mot - clé pour faire passer les arguments par référence. La sémantique des deux est très similaire. La seule différence réside dans l'initialisation de la variable flaged:
ref
nécessite que la variable soit initialisée avant de la passer à la fonction,out
ne le fait pas.out
nécessite que la variable soit initialisée à l'intérieur de la fonction,ref
non.
Les cas d'utilisation de ces deux mots clés sont également presque les mêmes, et leur utilisation trop fréquente est, je crois, considérée comme une odeur de code (bien qu'il existe des cas d'utilisation valides comme les modèles TryParse
et TryGetValue
).
Pour cette raison, quelqu'un pourrait-il expliquer pourquoi il existe deux outils très similaires en C # pour des cas d'utilisation aussi étroits?
En outre, sur MSDN , il est indiqué qu'ils ont un comportement d'exécution différent:
Bien que les mots clés ref et out provoquent des comportements d'exécution différents, ils ne sont pas considérés comme faisant partie de la signature de la méthode au moment de la compilation.
En quoi leur comportement à l'exécution est-il différent?
Conclusion
Les deux réponses semblent correctes, merci à vous deux. J'ai accepté les jmoreno parce que c'est plus explicite.
la source
ref
C ++; vers des pointeurs vers le pointeur objet (ou primitif) en question. c'est-à-dire queInt32.TryParse(myStr, out myInt)
(C #) est "exécuté" de la même manière queint32_tryParse(myStr, &myInt)
(C); la seule différence étant certaines contraintes imposées par le compilateur pour éviter les bugs. (Je ne posterai pas cela comme réponse parce que je peux me tromper sur la façon dont cela fonctionne dans les coulisses, mais c'est ainsi que j'envisage que cela fonctionne [parce que cela a du sens])Réponses:
Au moment où cette question a été posée, l'article MSDN était subtilement incorrect (il a depuis été corrigé ). Au lieu de "provoquer un comportement différent", cela devrait être "nécessite un comportement différent".
En particulier, le compilateur applique des exigences différentes pour les deux mots clés, même si le même mécanisme (IL) est utilisé pour activer le comportement.
la source
out
paramètre ou non l'attribution d'unref
paramètre, mais l'IL qu'il émet n'est qu'une référence dans les deux cas. Est-ce exact?out T
etref T
sont rendus identiques dans d'autres langages CLI tels que VB.Net ou C ++ / CLI.voici un article intéressant sur le sujet qui pourrait répondre à votre question:
http://www.dotnetperls.com/ref
point d'intérêt:
"La différence entre ref et out n'est pas dans le Common Language Runtime, mais dans le langage C # lui-même."
mise à jour:
le développeur principal de mon travail vient de corroborer la réponse de @ jmoreno, alors assurez-vous de la lire !.
la source
string
a à voir avec tout cela?Runtime ? Absolument aucun. Vous ne pouvez pas surcharger une méthode avec les mêmes paramètres qui ne diffèrent que par mot-clé ref ou out.
Essayez de compiler ceci et vous obtiendrez une erreur de compilation "La méthode avec la même signature est déjà déclarée":
Pour répondre à cette question: "... pourquoi il existe deux outils très similaires en C # pour des cas d'utilisation aussi étroits?"
Du point de vue de la lisibilité du code et de l'API, il y a une énorme différence. En tant que consommateur de l'API, je sais que lorsque "out" est utilisé, l'API ne dépend pas du paramètre out. En tant que développeur d'API, je préfère "out" et n'utilise "ref" que lorsque cela est absolument (RAREMENT!) Nécessaire. Voir cette référence pour une grande discussion:
/programming/1516876/when-to-use-ref-vs-out
Informations de support: j'ai compilé la méthode suivante et l'ai démontée. J'ai utilisé les mots clés ref et out (out dans cet exemple), mais le code assembleur n'a pas changé, sauf pour une référence d'adresse comme je m'y attendais:
00000000 push ebp
00000001 mov ebp, esp
00000003 push edi
00000004 push esi
00000005 push ebx
00000006 sub esp, 34h
00000009 xor eax, eax
0000000b mov dword ptr [ebp-10h], eax
0000000e mov dword ptr [ebp-1Ch], eax
00000011 mov dword ptr [ebp-3Ch], ecx
00000014 mov dword ptr [ebp-40h], edx
00000017 cmp dword ptr ds: [008B1710h], 0
0000001e je 00000025
00000020 appel 6E6B601E
00000025 nop
param = 0;
00000026 mov eax, dword ptr [ebp-40h]
00000029 xor edx, edx
0000002b mov dword ptr [eax], edx
}
0000002d nop 00000035 ret
0000002e lea esp, [ebp-0Ch]
00000031 pop ebx
00000032 pop esi
00000033 pop edi
00000034 pop ebp
Suis-je en train de lire correctement l'assemblage?
la source