Byval et byref [Résolu]

Signaler
Messages postés
173
Date d'inscription
dimanche 20 juillet 2003
Statut
Membre
Dernière intervention
24 août 2020
-
Messages postés
2235
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
15 septembre 2020
-
bonjour j'essaie de comprendre la signification et la différence entre byval et byref
dans votre exemple ici ou vous inversez les valeurs de x et y en partant de 10 et 20
quel est l'intérêt dans l'exemple en byval de partir de 10 et 20 pour arriver à 10 et 20 et non pas à 20 et 10 ; autrement dit dans ce cas de byval la procédure ne fait rien donc quel est son intérêt??
donc quelqu'un peut il m'expliquer clairement avec si possible un ou des exemples la différence et l'intérêt de byval et byref
à l'avance merci
--

8 réponses

Messages postés
14749
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
18 septembre 2020
433
Bonjour
dans votre exemple ici
sans lien vers cet exemple impossible de te dire exactement pourquoi 10 et 20....

Donc on va repartir de 0.

Une variable c'est un emplacement de mémoire (A) qui pointe vers un autre emplacement (B)
La donnée est stockée dans l'emplacement B, dans A il y a l'adresse de B, sa référence.

En .Net, il y a 2 types de variables:
  • les types valeurs
  • les types références.


C'est leur comportement par défaut qui les distingues.
  • Type Valeur

Dim toto as Integer 'on crée l'emplacement A(toto)
toto = 123456 'on crée l'emplacement B(toto) et on met son adresse dans A(toto)
Dim tutu as Integer 'on crée l'emplacement A(tutu)
tutu = toto 'on copie le contenu de B(toto) dans B(tutu), puis on mets l'adresse de B(tutu) dans A(tutu)
toto = 654321 'ceci ne modifie pas tutu, car toto et tutu pointent vers 2 emplacements différents, deux valeurs différentes.
  • Type Référence

Dim tata As List(Of String) 'on crée l'emplacement A(titi)
tata = New List(Of String) From {
    "Mot 1",
    "Mot 2",
    "Mot 3"
} 'on crée l'emplacement B(titi) et on met son adresse dans A(titi)

Dim titi 'on crée l'emplacement
titi = tata 'on met l'emplacement de B(tata) dans A(titi)

tata(1) = "Nouveau mot 2" 'ceci change aussi titi(1) car tata et titi pointent vers la même valeur



Par extension, quand on passe un paramètre à une méthode, sans les mots clés byval ou byref, c'est le même comportement qui est effectif.

Les mots clé byval et byref servent à inverser ce comportement:
  • passer la valeur d'un type référence
  • passer la référence d'un type valeur


mettre byval sur un type valeur ne sert à rien, pas plus que byref sur un type référence.
Messages postés
173
Date d'inscription
dimanche 20 juillet 2003
Statut
Membre
Dernière intervention
24 août 2020

Désolé je n'ai pas été assez précis
je me référais au tutorial Byref et Byval mis à jour par vos soins le 22 septembre 2017
dans lequel vous évoquiez la procédure Swap d'inversion des valeurs X et Y qui selon qu'on passait les arguments par référence donnait 20 et 10 alors qu'on partait de 10 et 20
et donnait 10 et 20 alors qu'on partait de 10 et 20 si on passait par valeur
ma question était : a quoi sert le par valeur si dans ce cas la procédure ne fait rien?
je me permets de vous soumettre les résultats de mes manip pour voir si vous pouvez m'aider à comprendre ; excusez les longueurs mais je n'ai pas réussi à faire plus court
voir ci dessous
à l'avance merci





si je mets ce code:


Module Module1
 
    Sub Main()
 
        Dim X As Integer
 
        X = 10
        Carre(X)
        Console.WriteLine(X)
        X = X + X
        Console.WriteLine(X)
        Console.ReadLine()
    End Sub
    Sub Carre(ByRef nombre As Integer)
        nombre = nombre * nombre
    End Sub
End Module
il m'affiche 100 et 200 

pourquoi car je lui ai dit console.writeline(x) et non pas console.writeline(Carre(X)) et si je lui mets console.writeline(Carre(X)) il me dit cette expression ne produit pas de valeur alors que Carre(X) pour moi a une valeur et elle est de 100 

si je mets cette autre code 


Module Module1
 
    Sub Main()
 
        Dim X As Integer
 
        X = 10
        Carre(X)
        Console.WriteLine(X)
        X = X + X
        Console.WriteLine(X)
        Console.ReadLine()
    End Sub
    Sub Carre(ByVal nombre As Integer)
        nombre = nombre * nombre
    End Sub
End Module
là il m'affiche 10 et 20 donc à quoi sert la fonction dans ce cas si elle ne fait rien

si j'écris


Module Module1
 
    Sub Main()
 
        Dim X As Integer
 
        X = 10
        Carre(X)
        Console.WriteLine(X)
        X = X + X
        Console.WriteLine(X)
        Console.ReadLine()
    End Sub
    Function Carre(ByRef nombre As Integer)
        nombre = nombre * nombre
        Return nombre
    End Function
End Module
il m'affiche 100 et 200 


et si je mets


Module Module1
 
    Sub Main()
 
        Dim X As Integer
 
        X = 10
        Carre(X)
        Console.WriteLine(X)
        X = X + X
        Console.WriteLine(X)
        Console.ReadLine()
    End Sub
    Function Carre(ByVal nombre As Integer)
        nombre = nombre * nombre
        Return nombre
    End Function
End Module

il m'affiche 10 et 20 donc il ne traite pas la fonction Carre pour moi il devrait me mettre 100 et 20 puisque le byval lui impose de ne pas modifier la variable en dehors de la fonction

et pourquoi cette différence entre procédure et fonction

pouvez vous sans abuser de votre temps essayer de m'éclaircir sur ces notions car je n'y comprends pas et je ne vois pas leur utilité
cordialement à vous
Messages postés
14749
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
18 septembre 2020
433
Depuis le temps que tu utilises ce forum, tu ne sais toujours pas poster un code en couleurs, avec de l'indentation, des ascenseurs, des numéros de ligne..... VB95 et moi faisait cet effort pour essayer de t'aider.
La moindre des choses serait d'en faire autant pour nous simplifier la vie. Je te rappelle que nous sommes bénévoles.

Petit tuto
https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code

ensuite, je te dis
sans lien vers cet exemple ....


et tu réponds
je me référais au tutorial Byref et Byval mis à jour par vos soins le 22 septembre 2017
, des tutos y'en a des milliers, je ne vais pas m'amuser à faire une recherche juste pour te répondre.
C'est un lien que je t'ai demandé....

ma question était : a quoi sert le par valeur si dans ce cas la procédure ne fait rien?

Sans avoir lu ton code, ni le tuto je dirais à te montrer la différence.
Messages postés
2235
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
15 septembre 2020
113 >
Messages postés
14749
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
18 septembre 2020

Salut Whis
J'ai retrouvé le tuto dont il parle : https://codes-sources.commentcamarche.net/faq/182-difference-entre-byref-et-byval-pour-vb6-ou-vba
Et de plus c'est toi l'auteur !
Messages postés
14749
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
18 septembre 2020
433 >
Messages postés
2235
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
15 septembre 2020

Salut, non c'est CrazyMan19 l'auteur, moi j'ai du corrigé des fautes ou remettre en forme avec la migration CCM.
En plus c'est un tuto VB6 et pas VB.net.

Mais c'est pas la question. Il se réfère à un truc, c'est à lui de donner la référence, pas à nous de chercher pour lui
Messages postés
14749
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
18 septembre 2020
433 >
Messages postés
14749
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
18 septembre 2020

Quand on regarde les différences de ma dernière intervention, j'ai ajouté les balises de code
Messages postés
2235
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
15 septembre 2020
113 >
Messages postés
14749
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
18 septembre 2020

Mille excuses alors Whis !
Quoiqu'il en soit que ce soit VB6 ou VB Net le principe est identique
Messages postés
2235
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
15 septembre 2020
113
Bonjour
Tout ce que dit Whismeril est tout à fait exact .
Cependant avec un exemple la subtilité de la chose te sera beaucoup plus claire
Considérons le code suivant avec un Label dans la Form
Public Class Form1

    Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown

        Dim A As Integer = 1  ' on créer une variable A
        Label1.Text = A.ToString  ' on affiche la valeur de A dans le Label
        For i = 0 To 10
            System.Threading.Thread.Sleep(2000) ' attendre 2 secondes
            Addition(A)
            Label1.Text = A.ToString  ' on affiche la valeur de A dans le Label
            Label1.Refresh()
        Next i

    End Sub

    Private Sub Addition(ByVal Nombre As Integer)

        Nombre = Nombre + 1

    End Sub

End Class

J'ai mis un Handles MyBase.Shown pour que l'on puisse voir la boucle évoluer dans la Form .

Maintenant intéressons-nous à la Sub Addition et lance le programme avec ByVal puis avec ByRef .
1) avec
 ByVal Valeur as Integer 
on remarque que le Label contient toujours 1 . Si le paramètre A est passé par valeur Nombre dans la fonction Addition est bien augmenté de 1 mais n'est pas répercuté dans la boucle For
2) avec
 ByRef Valeur as Integer 
Nombre est passé par référence à la variable A dans la boucle For et fait référence à ce A . En sortie de la Sub Addition Nombre est bien augmenté de 1 à chaque boucle et comme Nombre fait référence à A ce même A est aussi augmenté de 1 dans la boucle For .

L'exemple peut te paraître simpliste mais la compréhension et l'utilisation de ByRef peut être très utile dans le code . Cela permet à une variable définie dans une Procédure de pouvoir être modifiée dans d'autres Sub ou Fonction appelées par cette même Procédure .
Surtout si la Procédure est dans une Form et que la Sub ou la Fonction est dans une Classe

Messages postés
2235
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
15 septembre 2020
113
D'abord tu confonds les Sub et les Function
Une Sub ne renvoie pas de valeur alors qu'une Function si ( la Function se termine par le mot
 Return 
avec une variable ) . Lorsque on utilise une Function il est conseillé de se servir de sa valeur de retour dans le code appelant cette Function .

Reprenons tes 4 modules
Module 1
Module Module1
     Sub Main()
         Dim X As Integer
         X = 10
         Carre(X) ' une Sub : vu le Byref au retour X = 100
         Console.WriteLine(X)
         X = X + X ' X = 200
         Console.WriteLine(X)
         Console.ReadLine()
    End Sub
    
    Sub Carre(ByRef nombre As Integer)
        nombre = nombre * nombre
    End Sub
End Module
' il m'affiche 100 et 200 


Module 2
Module Module2
 
    Sub Main()
         Dim X As Integer
         X = 10
        Carre(X) ' Sub avec Byval :' X vaut toujours 10  
        Console.WriteLine(X)
        X = X + X
        Console.WriteLine(X)
        Console.ReadLine()
    End Sub
    
Sub Carre(ByVal nombre As Integer)
        nombre = nombre * nombre
    End Sub
End Module

Là il m'affiche 10 et 20 donc à quoi sert la fonction dans ce cas si elle ne fait rien
Tout à fait normal : où vois-tu une Function ? tu appelles bien la Sub
Carre(X)

Mais elle ne sert à rien dans le code .


Module 3
Module Module3
 
    Sub Main()
         Dim X As Integer
         X = 10
         Carre(X) ' une Function : là tu utilises la fonction avec le ByRef X = 100
         Console.WriteLine(X)
         X = X + X ' X = 200
         Console.WriteLine(X)
         Console.ReadLine()
     End Sub
     Function Carre(ByRef nombre As Integer)
        nombre = nombre * nombre
        Return nombre
    End Function
End Module

il m'affiche 100 et 200 : c'est le ByRef qui permet que X soit égal à 100 au retour de la fonction Carre . Dans ca cas Carre devrait être une Sub sans le
Return nombre 



Module4
Module Module4
 
    Sub Main()
         Dim X As Integer
        X = 10
        Carre(X) ' tu n'affectes pas à X la valeur retournée par la Function
        ' il faudrait mettre X = Carre(X) pour avoir 100 et 200
        Console.WriteLine(X)
        X = X + X
        Console.WriteLine(X)
        Console.ReadLine()
    End Sub
    Function Carre(ByVal nombre As Integer)
        nombre = nombre * nombre
        Return nombre
    End Function
End Module

Tu dis : il m'affiche 10 et 20 donc il ne traite pas la Function Carre pour moi il devrait me mettre 100 et 20 puisque le ByVal lui impose de ne pas modifier la variable en dehors de la fonction
La Function Carre est bien traitée mais tu ne te sers pas de sa valeur de retour . donc X reste à 10 une fois la Function traitée et tu afficheras 10 et 20 .

Messages postés
173
Date d'inscription
dimanche 20 juillet 2003
Statut
Membre
Dernière intervention
24 août 2020

Merci de ta réponse qui maintenant m'aide partiellement

si je mets le code suivant

Sub Main()

        Dim X As Integer
        Dim B As Integer
        X = 10
        Carre(X)
        B = Carre(X)

        Console.WriteLine(B)
        X = X + X
        Console.WriteLine(X)
        
        Console.ReadLine()

    End Sub
    Function Carre(ByVal nombre As Integer)

        nombre = nombre * nombre
        Return nombre

    End Function


il m'affiche bien 100 et 20 donc le byval a permis à X de ne pas être modifié
Mais si je veux utiliser une sub qui ne retourne pas de valeur cela ne marche pas
si je mets
Sub Main()

        Dim X As Integer
        Dim B As Integer
        X = 10
        Carre(X)
        B = Carre(X)

        Console.WriteLine(B)
        X = X + X
        Console.WriteLine(X)
        
        Console.ReadLine()

    End Sub
    Sub Carre(ByVal nombre As Integer)

        nombre = nombre * nombre


    End Sub

cela ne marche pas il me dit comme cause d'erreur
B = Carre(X)

cette expression ne produit pas de valeur
comment contourner cette difficulté
merci à l'avance de ta réponse et de ton aide


--
Messages postés
2235
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
15 septembre 2020
113
Bonjour
Quand tu comprendras la différence entre une sub ( sous-programme) et une fonction tu auras compris la raison de cette erreur . Et je pense te l'avoir expliqué

Sub Main()

        Dim X As Integer
        Dim B As Integer
        X = 10
        Carre(X) ' ligne inutile
        B = Carre(X) ' c'est une fonction

        Console.WriteLine(B)
        X = X + X
        Console.WriteLine(X)
        
        Console.ReadLine()

    End Sub
    Function Carre(ByVal nombre As Integer)

        nombre = nombre * nombre
        Return nombre

    End Function


Sub Main()

        Dim X As Integer
        Dim B As Integer
        X = 10
        Carre(X) ' c'est un sous-programme là
        B = Carre(X) ' normal que l'erreur soit là un sous-programme ne renvoie pas de valeur

        Console.WriteLine(B)
        X = X + X
        Console.WriteLine(X)
        
        Console.ReadLine()

    End Sub
    Sub Carre(ByVal nombre As Integer)

        nombre = nombre * nombre
        ' dans une Sub pas de Return donc pas de variable en retour

    End Sub


Merci
J’ai compris
Quel est l’intérêt de la procédure par rapport à la fonction?
Merci
Messages postés
2235
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
15 septembre 2020
113
tu utilises une fonction si tu as besoin d'une valeur en retour .
sinon tu utilises un sous-programme ( Sub)
Attention tous les deux sont considérés comme des procédures .
Messages postés
2235
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
15 septembre 2020
113
Bonjour
Si les réponses que nous t'avons données te satisfont et que tu considères que le sujet peut être fermé prière de mettre ce post comme étant résolu avec le bouton adéquat .
Merci