OVH Cloud OVH Cloud

Byval ou byRef

13 réponses
Avatar
David Bouchard
Je cherche à savoir quel est la meilleure option des deux. J'ai une fonction
qui prend un type valeur (structure) comme argument et la, je me demande
qu'est-ce qui est le mieux entre passé la valeur byRef pour intéragir
directement sur celle-ci ou bien, la passé ByVal pour ensuite la retourner.
Par exemple, j'aurais créé une structure BiColor

public structure BiColor
dim Couleur1 as color
dim Couleur2 as color
end structure

et ensuite, je voudrais faire un traitement sur une variable de type BiColor
à l'aide d'une fonction comme ceci

Dim Val as BiColor
val.couleur1 = color.black
val.couleur2 = color.red

Traitement_Couleur(val) 'En la passant ByRef
ou
Val = Traitement_Couleur(val) 'En la passant ByVal

Public function Traitement_Couleur(byval Val as BiColor) as BiColor
Val.Couleur1 = Val.Couleur2
Val.Couleur2 = color.blue
return Val
end function

ou

Public Sub Traitement_Couleur(ByRef Val as BiColor)
Val.Couleur1 = Val.Couleur2
Val.Couleur2 = color.blue
end sub

Merci

David

3 réponses

1 2
Avatar
Zazar
Bonjour,

Mais si tu utilises ByVal ou ByRef pour une classe, le résultat sera le


même
finalement puisque une classe est un type référence, non? Autrement dit,


la
fonction Swap avec ByRef ou ByVal fonctionne dans les deux cas.



Bon, en fait, il semble que vous ne maitrisiez pas la différence entre les 2
:).

ByVal passe le contenu de la variable par valeur : la variable est recopiée.
ByRef passe le une réfèrence vers la variable.

Qu'est ce que cela signifie ?

1) Dans le cas d'une structure (ou tout autre type valeur)
Une variable d'un type valeur contient directement ses données.
Si on passe une telle variable par valeur, on a alors une copie des données
qui est effectuée et tout changement sur une des copies n'affecte pas
l'autre.
Exemple :
structure MyStruct
public MyData as string
end structure

sub MyMethod1() {
dim myValueVar as MyStruct
myValueVar.MyData = "bonjour"
MyMethod(myValueVar)
Console.WriteLine(myValueVar.MyData)
}

sub MyMethod2(ByVal MyStruct myParam) {
myParam.MyData = "bonsoir"
}

Cet exemple va afficher "bonjour", car myParam est une copie de myValueVar.

De même, si on fait :
sub MyMethod2(ByVal MyStruct myParam) {
myParam = new MyStruct()
myParam.MyData = "bonsoir"
}
Aucune modification n'est répercutée sur sur myValueVar.


Si on utilise ByRef au lieu de ByVal :
sub MyMethod2(ByRef MyStruct myParam) {
myParam.MyData = "bonsoir"
}

myParam devient une réfèrence vers myValueVar. Toute modification faîte sur
myParam est répercutée sur myValueVar. Le texte affiché est donc bonsoir.
De même, si on fait :
sub MyMethod2(ByRef MyStruct myParam) {
myParam = new MyStruct()
myParam.MyData = "bonsoir"
}
Les modifications sont effectuées sur myValueVar : la première ligne
réinitialise myValueVar à ses valeurs par défaut, la seconde affecte
"bonsoir" à myValueVar.MyData.


Enfin si on a :
function MyMethod2(ByVal MyStruct myParam) as MyStruct {
myParam.MyData = "bonsoir"
return myParam;
}

et qu'on modifie l'appel :
myValueVar = MyMethod2(myValueVar)
myParam est une copie de myValueVar, une modification sur myParam n'est pas
répercutée sur myValueVar. Cependant, à la sortie de la fonction, on affecte
la valeur de myParam à myValueVar. Ca veut dire que myValueVar devient en
fait une copie de myParam. Le texte affiché est donc bonsoir.

Une méthode Swap s'écrirait ainsi :

sub MyMethod() {
dim myValueVar, myValueVar2 as MyStruct
myValueVar.MyData = "bonjour"
myValueVar2.MyData = "bonsoir"
Swap(myValueVar, myValueVar2)
}

sub Swap(ByRef param1 as MyStruct, ByRef param2 as MyStruct) {
MyStruct tmp = param1 'tmp contient une copie de la structure référencée
par param1. tmp est donc une copie de myValueVar
param1 = param2 'la structure référencée par param1 (myValueVar)
contient désormais une copie de la structure référencée par param2
(myValueVar2). myValueVar contient donc une copie de myValueVar2
param2 = tmp 'la structure référencée par param2 (myValueVar2) contient
désormais une copie de tmp, lui même une copie de la valeur de myValueVar
avant l'appel à la fonction. Le Swap est donc terminé.
}

2) Maintenant, les classes (ou tout autre type réfèrence)
Une variable d'un type référence ne contient pas directement ses données
mais contient une réfèrence vers ses données.
Si on passe une telle variable par valeur, on a alors une copie de la
réfèrence qui est effectuée.

Exemple :
class MyClass
public MyData as string
end structure

sub MyMethod1() {
dim myValueVar as MyClass
myRefVar= new MyClass()
myRefVar.MyData = "bonjour"
MyMethod(myRefVar)
Console.WriteLine(myRefVar.MyData)
}

sub MyMethod2(ByVal MyClass myParam) {
myParam.MyData = "bonsoir"
}

myParam contient une copie de la réfèrence de myRefVar; autrement dit
myParam et myRefVar font tous les deux réfèrences au même objet et toute
modification faîte sur l'objet est donc commune aux 2 réfèrences.
Le code ci-dessus affiche donc bonsoir.

Si on fait :
sub MyMethod2(ByVal MyClass myParam) {
myParam = new MyClass();
myParam.MyData = "bonsoir"
}

Aprés l'exécution de la première ligne, myParam est une réfèrence vers un
nouvel objet différent de celui réfèrencé par myRefVar. Le code afficherait
donc "Bonjour".

Si on utilise ByRef au lieu de ByVal :
sub MyMethod2(ByRef MyClass myParam) {
myParam.MyData = "bonsoir"
}
MyParam est une réfèrence vers myRefVar qui est une réfèrence vers des
données. Autrement dit, myParam est une réfèrence vers une réfèrence vers
des données.
Dans l'exemple ci-dessus, on a aucun problème le texte affiché est bonsoir.

Si on fait :
sub MyMethod2(ByRef MyClass myParam) {
myParam = new MyClass()
myParam.MyData = "bonsoir"
}

LA première ligne signifie que
Les données réfèrencées par MyParam deviennent une réfèrence vers un
nouvel objet. Or, les données réfèrencées par myParam, c'est myRefVar.
MyRefVar réfèrence donc un nouvel objet.
le MyData de ce nouvel objet est ensuite mis à "bonsoir", le texte affiché
est donc "bonsoir".

Une fonction de Swap s'écrit donc ainsi :

sub MyMethod() {
dim myRefVar, myRefVar2 as MyClass
myRefVar = new MyClass() 'myRefVar contient une réfèrence vers un objet
: obj1
myRefVar2 = new MyClass() 'myRefVar2 contient une réfèrence vers un
objet : obj2
myRefVar.MyData = "bonjour"
myRefVar2.MyData = "bonsoir"
Swap(myValueVar, myValueVar2)
}

sub Swap(ByRef param1 as MyClass, ByRef param2 as MyClass) {
MyClass tmp = param1 'tmp contient les donnéees réfèrencées par param1.
tmp et myRefVar sont donc deux réfèrences vers obj1
param1 = param2 'Les données réfèrencées par param1 sont maintenant
égales aux données réfèrencées par param2 : myRefVar contient désormais la
même chose que myRefVar2, c'est à dire une réfèrence vers obj2
param2 = tmp 'et enfin les données réfèrencées par param1 sont
maintenant égales à tmp : yRefVar2 est une réfèrence vers obj1.
}

Si on faisait un passage par valeur :
sub Swap(ByVal param1 as MyClass, ByVal param2 as MyClass) {
MyClass tmp = param1 'tmp est une réfèrence vers obj1
param1 = param2 'param1 est une réfèrence vers obj2, mais ceci n'affecte
pas myRefVar1
param2 = tmp 'param2 est une réfèrence vers obj1, mais ceci n'affecte pas
myRefVar2
}

Les valeurs de param1 et param2 sont bien swappées, mais pas celles de
myRefVar1 et de myRefVar2.

Bon j'espère que j'ai réussi à être clair et que je ne me suis pas trompé en
écrivant ces explications.

--
Zazar
Avatar
Zazar
> Bon j'espère que j'ai réussi à être clair et que je ne me suis pas trompé


en
écrivant ces explications.



Je m'aperçois que j'ai mélangé du C# et du VB.NET pour compliquer un peu :)

--
Zazar
Avatar
David Bouchard
J'en reviens pas comment la différence est subtile mais grace à ton
explication élaborer, surtout le swap, j'ai enfin compris.

Merci beaucoup encore

David

"Zazar" a écrit dans le message
de news:

> Bon j'espère que j'ai réussi à être clair et que je ne me suis pas


trompé
en
> écrivant ces explications.

Je m'aperçois que j'ai mélangé du C# et du VB.NET pour compliquer un peu


:)

--
Zazar





1 2