Question

Quels sont les éléments à considérer lors du choix entre ByRef et ByVal.

Je comprends la différence entre les deux, mais je ne comprends pas tout à fait si ByRef économise des ressources ou si nous devons même nous en préoccuper dans l'environnement .Net.

Comment décidez-vous entre les deux si la fonctionnalité n'a pas d'importance dans une situation?

Était-ce utile?

La solution

Il y a beaucoup de désinformation à ce sujet. L’essentiel est que vous compreniez la différence entre les types de valeur et les types de référence , ainsi que différence entre passage par valeur et passage par référence .

Vous voulez presque toujours passer par valeur. Passer par référence revient presque toujours à "Je souhaite renvoyer plusieurs résultats, et pas seulement en ajoutant des éléments à une liste transmise". L'exemple classique d'une méthode utilisant la méthode de référence est le Int32.TryParse où la valeur renvoyée est un succès / un échec et où la valeur analysée est "renvoyée". par un paramètre out.

Autres conseils

La valeur par défaut est byValue pour TOUS les types, mais il est important de comprendre la signification des deux options pour un "type de référence". (une classe) par opposition à un type de valeur. (structs).

Pour un type de référence, si vous déclarez une variable de type référence dans une méthode, cette variable est un emplacement mémoire dans le cadre de pile de la méthode. Ce n'est pas sur le tas. Lorsque vous initialisez cette variable (à l'aide de new ou d'une fabrique, peu importe), vous avez créé un objet réel sur le tas et l'adresse de cet objet est stockée dans la variable de référence déclarée dans le cadre de la pile de vos méthodes.

Lorsque vous passez un type de référence à une autre méthode byVal, vous créez une copie de l'adresse stockée dans la pile de méthodes appelantes et transmettez la copie de cette valeur (l'adresse du pointeur) à la méthode appelée, où elle est stockée. un nouvel emplacement mémoire dans la pile de méthodes appelée. Dans la méthode appelée, la nouvelle variable clonée pointe directement sur le même objet du tas. Donc, l'utiliser peut changer les propriétés du même objet. Mais vous ne pouvez pas modifier l'objet tas auquel la variable de référence d'origine (sur la pile de méthodes appelantes) pointe. Si, dans la méthode appelée, j'écris

  myVar = new object();

La variable d'origine dans la méthode d'appel n'aura pas changé pour pointer vers un nouvel objet.

Si je passe un type de référence byRef, otoh, je passe un pointeur sur la variable déclarée dans la pile de méthodes d'appel (qui contient un pointeur sur l'objet sur le tas). Il s'agit donc d'un pointeur sur un pointeur sur l'objet . Il pointe vers l'emplacement de la mémoire sur la pile de méthodes appelantes, qui pointe vers l'objet du tas.
Alors maintenant, si je change la valeur de la variable dans la méthode appelée, en lui affectant un nouvel objet (), comme ci-dessus, puisqu'il s'agit d'un "référent" En ce qui concerne la variable dans la méthode d'appel, je change en fait l'objet vers lequel la variable de la méthode d'appel pointe. Ainsi, après le retour de la méthode appelée, la variable dans la méthode d'appel ne sera plus pointée sur le même objet d'origine sur le tas.

ByVal doit être votre "valeur par défaut". Utilisez-le sauf si vous avez une raison particulière d'utiliser ByRef

Passer un objet par ByVal dans .net ne fait pas de copie de l’objet et ne consomme pas plus de ressources que ByRef. Un pointeur est toujours transmis à la fonction. Le moteur d'exécution garantit simplement que vous ne pouvez pas modifier le pointeur dans votre fonction et renvoyer une valeur différente pour celui-ci. Vous pouvez toujours modifier les valeurs dans l'objet et vous verrez ces modifications en dehors de la fonction. C'est pourquoi ByRef est utilisé si rarement. Cela n'est nécessaire que si vous souhaitez qu'une fonction modifie l'objet qui revient; d'où un paramètre de sortie.

Utilisez " ByRef " uniquement si le paramètre est " output " paramètre. Sinon, utilisez "ByVal". Utilisation de "ByRef" sur des paramètres qui explicitement ne doivent pas renvoyer de valeurs est dangereux et peut facilement générer des bugs.

Je dirais que ByRef ne devrait jamais être utilisé - c'est une mauvaise pratique. J'appliquerais cela même à son cas typique d'utilisation permettant à une fonction de renvoyer plusieurs valeurs (via les paramètres de ByRef). Il serait préférable que la fonction renvoie une réponse structurée incluant ces valeurs de retour multiples. C’est plus clair et plus évident si une fonction ne renvoie que des valeurs via son instruction return.

Le marquage de certains arguments comme étant ByRef indique à l'utilisateur de votre fonction que la variable allouée à cet argument ** sera modifiée. ****

Si vous utilisez ByRef pour tous les arguments, il n'y aura aucun moyen de déterminer les variables modifiées par la fonction et celles qui viennent d'être lues par celle-ci. (à part regarder dans la source de la fonction!)

Selon Microsoft, choisir ByVal ou ByRef peut affecter les performances pour des valeurs suffisamment grandes (voir Passer des arguments par valeur et par référence (Visual Basic) ):

  

Performance. Bien que le mécanisme de passage puisse affecter les performances   de votre code, la différence est généralement insignifiante. Une exception   à ceci est un type de valeur passé à ByVal. Dans ce cas, Visual Basic   copie l'intégralité du contenu des données de l'argument. Par conséquent, pour un   grande valeur telle qu'une structure, il peut être plus efficace de passer   il ByRef.

[emphase ajoutée].

Sub last_column_process()
Dim last_column As Integer

last_column = 234
MsgBox last_column

trying_byref x:=last_column
MsgBox last_column

trying_byval v:=last_column
MsgBox last_column

End Sub

Sub trying_byref(ByRef x)
x = 345
End Sub

Sub trying_byval(ByRef v)
v = 555
End Sub

Beaucoup de confusion, je vais essayer de simplifier. Vous avez essentiellement 4 choix:

  1. Passer un type de valeur byVal
  2. Passer un type de valeur byRef
  3. Passer un objet parVal
  4. Passer un objet parRef

Certaines personnes disent que vous ne devriez jamais utiliser byRef. Bien qu'ils soient techniquement corrects, une chose est sûre. Vous devez JAMAIS utiliser le mot jamais . Si vous concevez un système à partir de rien, byRef doit être évité à tout prix. Son utilisation expose un défaut de conception. Cependant, travailler sur un système existant peut ne pas fournir autant de flexibilité pour mettre en œuvre une bonne conception. Parfois, vous devez faire des concessions, c’est-à-dire utiliser byRef. Par exemple, si vous pouvez obtenir une solution en 2 jours avec byRef, il peut être préférable de réinventer la roue et de prendre une semaine pour obtenir la même solution, juste pour éviter d’utiliser ByRef.

Résumé:

  1. Utilisation de byVal sur un type de valeur: transmet une valeur à une fonction. C’est le moyen privilégié de fonctions de conception.
  2. Utilisation de byRef sur un type de valeur: utile pour renvoyer plusieurs valeurs d’une fonction. Si vous créent une fonction qui doit renvoyer plusieurs valeurs à un système existant, cela peut être mieux que de créer un objet (et de définir des propriétés et de disposer), pour une fonction.
  3. Utilisation de byVal sur un objet: Passe le pointeur d’un objet à une fonction. La fonction peut modifier l'objet.
  4. Utilisation de byRef sur un objet: passe un pointeur sur un pointeur d’un objet sur une fonction. Permet changer l'objet pointé par l'appelant. Cela peut causer des difficile de trouver des bugs et je ne vois aucune bonne raison de l’utiliser. Ne veut pas dire qu'il n'y en a pas, mais s'il y en a peu et loin entre.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top