IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Une énigme sur le "sender byval"


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Homme Profil pro
    Enseignant
    Inscrit en
    Février 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2012
    Messages : 7
    Par défaut Une énigme sur le "sender byval"
    Bonjour

    J'espère trouver une réponse à une question qui me tarabuste depuis très longtemps - désolé si elle a déjà été posée.

    Voilà : dans les procédures évènementielles en VB, sender est une variable objet transmise par valeur. Or, les propriétés de l'objet désigné par sender sont accessibles en écriture, ce qui me semble a priori parfaitement contradictoire.

    Une bonne âme pourrait-elle éclairer ma lanterne ?

  2. #2
    Membre Expert
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Par défaut
    Bonsoir,

    (Note j'utilise la terminologie pointeurs issue du C pour faciliter la compréhension (j'espère ))
    Tous les "sender" habituels sont des contrôles, donc des classes ; et il faut bien comprendre que quand on a Dim btn As Button en fait btn contient un "pointeur" sur un bouton.
    Par conséquent le passage par valeur créé une copie de ce pointeur, soit un autre pointeur qui pointe sur la même chose et ainsi les modifications de l'un se répercute sur l'autre.

    Un test simple tu créés une Structure simple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Public Structure StructButton
        Public Property Data As Integer
    End Structure
    et tu le passes manuellement comme sender d'un évènement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    ' Gestionnaire d'évènement (note pas de handles à la fin)
    Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
        ' vérification du sender
        If TypeOf sender Is StructButton Then
            ' conversion du sender
            Dim sBtn As StructButton = DirectCast(sender, StructButton)
            ' affichage
            MessageBox.Show(sBtn.Data)
            ' modification
            sBtn.Data = 42
        End If
    End Sub
     
    ' Constructeur du formulaire (Form1)
    Sub New()
        ' This call is required by the designer.
        InitializeComponent()
     
        ' Add any initialization after the InitializeComponent() call.
        ' On instancie un StructButton
        Dim sBtn as New StructButton
        ' Peut importe la syntaxe ici, si tu ne la connais pas
        ' Elle permet de lancer notre version modifiée de Button1_Click
        AddHandler Button1.Click, Sub() Button1_Click(sBtn, EventArgs.Empty)
    End Sub
    Normalement au premier passage, s'affichera 0 soit la valeur initiale de Data qui est ensuite changée en 42.
    Mais tu auras beau cliquer tu obtiendras toujours 0, parce que la modification n'est pas répercutée.
    En effet comme il s'agit d'une structure, tu passes une copie de l'objet tout entier, et donc les modifications de l'un ne sont pas visibles sur l'autre (et comme à chaque appel c'est le sBtn initial qui est lancé il a toujours son Data à 0).

    Voilà j'espère que c'est pas un peu trop brouillon, j'encourage au passage quelqu'un qui maitrise mieux ça que moi à reformuler/corriger le tout parce que bien que je sache en gros ; je n'ai pas forcément la terminologie ou les bons concepts.

    Cordialement !

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par MoonlightSwamper Voir le message
    Voilà : dans les procédures évènementielles en VB, sender est une variable objet transmise par valeur. Or, les propriétés de l'objet désigné par sender sont accessibles en écriture, ce qui me semble a priori parfaitement contradictoire.
    Ce n'est pas contradictoire ; tu peux changer les propriétés de sender, mais tu ne peux pas remplacer sender... enfin, tu peux le faire, mais ça n'aura d'effet que dans la méthode courante, le code appelant ne verra pas la modification.

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    700
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 700
    Par défaut
    Bonjour,

    Il faut différencier deux choses au niveau de l'argument : son type et la façon dont on le passe.
    C'est bien expliqué .
    sender est de type Référence et on le passe ByVal, ce qui permet d'interagir avec ses propriétés sans possibilité d'agir sur lui même.

    Dans la suite de Sehnsucht et tomlev, un petit test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            If sender Is Button1 Then
                MessageBox.Show(sender.ToString)
            End If
            Button1 = Button2
            MessageBox.Show(sender.ToString)
            MessageBox.Show(CStr(sender.Equals(Button2)))
            MessageBox.Show(CStr(Object.ReferenceEquals(sender, Button2)))
        End Sub
    montre que sender reste Button1, mais on a modifié plusieurs de ses membres entre autre il perd la main sur cet événement (les clics suivants sur lui sont inopérants).

    Là est le fonctionnement. Le pourquoi... , j'avance cette hypothèse qui me semble induite :
    Dans ce contexte, il est primordial qu'on ne puisse modifier l’objet (tout en lui permettant d'être réactif), sans créer de grave dysfonctionnement de l'application.

  5. #5
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    bonjour MoonlightSwamper.

    Non il n' y a pas d'enigme la-dessus du tout.
    Il suffit de repotasser la doc officielle de vb.net.
    Le VB.Net ne l'oublions pas n'est pas le C#,a fortiori le C++ car il n'as pas de variable de type "pointeur"......
    Comme fait alors le compilateur vb.net pour passer des adresses ou des valeurs?Derriere les coulisses........
    La convention implicite du vb.net est :
    1/ les variables types valeur "simples" tel un entier,un double ou string un boolean sont passes par defaut par valeur (byVal) sauf specification contraire par l'implementeur.
    Si tu mets byRef vb.net considere que tu veux faire un passage par adresse de ta variable et donc la valeur modifie se repercute sur la valeur initiale.....

    2/ les variables "complexes" savoir:tableau,object,structure sont passees d'autorite par adresse c.à.d byRef .
    Le specificateur "byVal" n'a aucun effet dans ce cas...et toute modif de variable se repercute sur la variable initiale..............
    C'est la une logique interne tant qu'on travaille en vb.net.....

    voic un code exemple -pour types simples- qui illlustre ce qui precede:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    Public Class Form2
     
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
          'variable interne  à cette sub(raisonnement est equivalent si on remplace cette sub par cette class) 
     
       'type valeur simple autre que tableau peuvent etre passe
            'et la difference est nettement visible.....
     
            Dim oneDouble As Double
            Dim oneInteger As Integer
     
            oneInteger = 15
            oneDouble = 100.0
            '- soit par valeur
            passageParValeur(oneInteger, oneDouble)
     
            TextBox1.Text = TextBox1.Text & oneInteger.ToString & vbCrLf
            TextBox1.Text = TextBox1.Text & oneDouble.ToString
            '- soit par adresse 
            passageParReference(oneInteger, oneDouble)
            TextBox2.Text = TextBox2.Text & oneInteger.ToString & vbCrLf
            TextBox2.Text = TextBox2.Text & oneDouble.ToString
     
        End Sub
        'passage par valeur
        Private Sub passageParValeur(ByVal xInteger As Integer, ByVal xDouble As Double)
     
            xInteger = xInteger + 1
            xDouble = xDouble + 1.0
        End Sub
        'passage par Adresse
        Private Sub passageParReference(ByRef xInteger As Integer, ByRef xDouble As Double)
     
            xInteger = xInteger + 1
            xDouble = xDouble + 1.0
        End Sub
     
    End Class
    et un code exemple -pour types complexes- :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
     
    Public Class Form1
     
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            'variable interne à cette sub(raisonnement est equivalent si on remplace cette sub par cette classe) 
            '
            '2 tableaux sont passes par valeur (mais vb.net travaille directement sur l'adressse)
            Dim arDouble(1) As Double
            Dim arStr(1) As String
     
            'type object =>idem
            Dim objClass As SampleClass = New SampleClass
     
            'type object controle =>idem
            Dim myButton As Button = New Button
            myButton.BackColor = Color.Red
     
            '- passage  par valeur
            objClass.MyProperty = 1000.0
     
            arDouble(0) = 10.0
            arDouble(1) = 20.0
     
            arStr(0) = "blablaInMain1"
            arStr(1) = "blablaInMain2"
     
     
            passageParValeur(objClass, myButton, arDouble, arStr)
            TextBox1.Text = TextBox1.Text & objClass.MyProperty.ToString & vbCrLf
            For i As Integer = 0 To arDouble.Length - 1
                TextBox1.Text = TextBox1.Text & arDouble(i) & vbCrLf
            Next
            For i As Integer = 0 To arStr.Length - 1
                TextBox1.Text = TextBox1.Text & arStr(i) & vbCrLf
            Next
            TextBox1.Text = TextBox1.Text & myButton.BackColor.ToString & vbCrLf
     
     
        End Sub
        Private Sub passageParValeur(ByVal oneObject As SampleClass, ByVal xButton As Button, _
                ByVal arDouble() As Double, ByVal arStr() As String)
            'modifie dans cette sub(<=> cette classe)
            oneObject.MyProperty = oneObject.MyProperty + 1.0
            xButton.BackColor = Color.Blue
            arDouble(0) = arDouble(0) + 1.0
            arDouble(1) = arDouble(1) + 1.0
     
            arStr(0) = "blablaInSub1"
            arStr(1) = "blablaInSub2"
        End Sub
     
     
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            'les memes variables sont passeses cette fois par adresse
            'mais le resultat est identique au passage par valeur.
     
            Dim arDouble(1) As Double
            Dim arStr(1) As String
     
            Dim objClass As SampleClass = New SampleClass
     
            '- passage  par Adresse
            objClass.MyProperty = 1000.0
            Dim myButton As Button = New Button
            myButton.BackColor = Color.Red
     
            arDouble(0) = 10.0
            arDouble(1) = 20.0
     
            arStr(0) = "blablaInMain1"
            arStr(1) = "blablaInMain2"
     
            passageParReference(objClass, myButton, arDouble, arStr)
            TextBox2.Text = TextBox2.Text & objClass.MyProperty.ToString & vbCrLf
            For i As Integer = 0 To arDouble.Length - 1
                TextBox2.Text = TextBox2.Text & arDouble(i) & vbCrLf
            Next
            For i As Integer = 0 To arStr.Length - 1
                TextBox2.Text = TextBox2.Text & arStr(i) & vbCrLf
            Next
            TextBox2.Text = TextBox2.Text & myButton.BackColor.ToString & vbCrLf
     
        End Sub
        Private Sub passageParReference(ByRef oneObject As SampleClass, ByRef xButton As Button, _
                                        ByRef arDouble() As Double, ByRef arStr() As String)
            'modifie dans cette sub(<=> cette classe)
            oneObject.MyProperty = oneObject.MyProperty + 1.0
            xButton.BackColor = Color.Blue
            arDouble(0) = arDouble(0) + 1.0
            arDouble(1) = arDouble(1) + 1.0
     
            arStr(0) = "blablaInSub1"
            arStr(1) = "blablaInSub2"
        End Sub
    End Class
    Public Class SampleClass
        Private myField As Double
     
        Private m_MyProperty As Double
        Public Property MyProperty() As Double
            Get
                Return m_MyProperty
            End Get
            Set(ByVal value As Double)
                m_MyProperty = value
            End Set
        End Property
     
     
     
    End Class
    bon code.......

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par MABROUKI Voir le message
    Le VB.Net ne l'oublions pas n'est pas le C#,a fortiori le C++ car il n'as pas de variable de type "pointeur"......
    VB.NET n'est certes pas C#, mais en l'occurrence l'explication est la même, et n'a rien à voir avec les pointeurs...

    Citation Envoyé par MABROUKI Voir le message
    2/ les variables "complexes" savoir:tableau,object,structure sont passees d'autorite par adresse c.à.d byRef .
    Le specificateur "byVal" n'a aucun effet dans ce cas...et toute modif de variable se repercute sur la variable initiale..............
    C'est la une logique interne tant qu'on travaille en vb.net.....
    C'est complètement faux

    - D'abord, il n'y a pas de notion de "types simples" et de "types complexes", il n'y a que des types valeur et des types référence. Et les structures sont des types valeur, qui ne sont sûrement pas passés par référence par défaut...

    - Ensuite, la notion de passage par valeur ou de passage par référence est complètement décorrélée de la notion de type valeur ou type référence. Tous les types sont passés par valeur (ByVal) par défaut, y compris les types référence..

    Je rappelle que pour les types référence, la valeur de la variable est une référence. Dans le cas du passage par valeur d'un type référence, c'est une référence qui est passée par valeur. la variable locale de la fonction appelante et le paramètre de la fonction appelée contiennent la même référence, et "pointent" donc sur le même objet, mais ce sont deux variables différentes, avec des emplacement de stockage distincts.

    Le code suivant illustre bien les différents cas de figure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    Sub Main
        Dim va As New IntStruct()
        Dim vb As New IntStruct()
        Dim ra As New IntClass()
        Dim rb As New IntClass()
     
        Console.WriteLine("Value type by value")
        va.Value = 10
        vb.Value = 10
        Console.WriteLine("Before: va.Value = {0}, vb.Value = {1}", va.Value, vb.Value)
        ValueTypeByVal(va, vb)
        Console.WriteLine(" After: va.Value = {0}, vb.Value = {1}", va.Value, vb.Value)
        Console.WriteLine()
     
        Console.WriteLine("Reference type by value")
        ra.Value = 10
        rb.Value = 10
        Console.WriteLine("Before: ra.Value = {0}, rb.Value = {1}", ra.Value, rb.Value)
        ReferenceTypeByVal(ra, rb)
        Console.WriteLine(" After: ra.Value = {0}, rb.Value = {1}", ra.Value, rb.Value)
        Console.WriteLine()
     
        Console.WriteLine("Value type by reference")
        va.Value = 10
        vb.Value = 10
        Console.WriteLine("Before: va.Value = {0}, vb.Value = {1}", va.Value, vb.Value)
        ValueTypeByRef(va, vb)
        Console.WriteLine(" After: va.Value = {0}, vb.Value = {1}", va.Value, vb.Value)
        Console.WriteLine()
     
        Console.WriteLine("Reference type by reference")
        ra.Value = 10
        rb.Value = 10
        Console.WriteLine("Before: ra.Value = {0}, rb.Value = {1}", ra.Value, rb.Value)
        ReferenceTypeByRef(ra, rb)
        Console.WriteLine(" After: ra.Value = {0}, rb.Value = {1}", ra.Value, rb.Value)
        Console.WriteLine()
    End Sub
     
    Structure IntStruct
        Property Value As Int32
    End Structure
     
    Class IntClass
        Property Value As Int32
    End Class
     
    Sub ValueTypeByVal(ByVal x As IntStruct, ByVal y As IntStruct)
        x.Value = 42
        y = New IntStruct() ' Value = 0
    End Sub
     
    Sub ReferenceTypeByVal(ByVal x As IntClass, ByVal y As IntClass)
        x.Value = 42
        y = New IntClass() ' Value = 0
    End Sub
     
    Sub ValueTypeByRef(ByRef x As IntStruct, ByRef y As IntStruct)
        x.Value = 42
        y = New IntStruct() ' Value = 0
    End Sub
     
    Sub ReferenceTypeByRef(ByRef x As IntClass, ByRef y As IntClass)
        x.Value = 42
        y = New IntClass() ' Value = 0
    End Sub
    On voit bien que dans le cas du passage de type référence par valeur, modifier une propriété de x est répercuté sur ra (puisque les 2 pointent sur le même objet), mais qu'affecter une nouvelle valeur à y n'a aucun effet sur rb (ce sont 2 variables distinctes)

    Dans le cas du passage par valeur d'un type valeur, on voit bien que la méthode n'a aucune effet sur va et vb, ce qui prouve bien que les structures ne sont pas "toujours passées par référence" comme tu le disais.

    Je t'invite à lire attentivement cet article (il concerne C#, mais le principe est exactement le même en VB.NET)

  7. #7
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut
    [EDIT] devancé par tomlev ^^ [/EDIT]

    @MABROUKI, Ce que vous avez dit est plus ou moins complet à un détail prêt

    Citation Envoyé par MABROUKI Voir le message
    2/ Le specificateur "byVal" n'a aucun effet dans ce cas...et toute modif de variable se repercute sur la variable initiale..............
    N'est pas tout à fait juste, car comme tomlev l'a écrit :

    Citation Envoyé par tomlev Voir le message
    Ce n'est pas contradictoire ; tu peux changer les propriétés de sender, mais tu ne peux pas remplacer sender... enfin, tu peux le faire, mais ça n'aura d'effet que dans la méthode courante, le code appelant ne verra pas la modification.
    Ce que vous mélangez, c'est la notion de variable avec la notion d'objet.
    En faisant un programme on voit mieux ce que tomlev expliquait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    Public Class Form1
     
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            Dim unePersonne = New personne("x", "y")
            Debug.WriteLine(unePersonne) ' x y
     
            changeObjetByRef(unePersonne)
            Debug.WriteLine(unePersonne) ' by Ref => Changement de l'objet
     
            changeObjetByVal(unePersonne)
            Debug.WriteLine(unePersonne) ' by Ref => Pas de changement
        End Sub
     
        Public Sub changeObjetByRef(ByRef unePersonne As personne)
            unePersonne = New personne("by", "Ref")
        End Sub
     
        Public Sub changeObjetByVal(ByVal unePersonne As personne)
            unePersonne = New personne("by", "Val")
        End Sub
    End Class
     
    Public Class personne
        Public nom As String
        Public prénom As String
     
        Public Sub New(nom As String, prenom As String)
            Me.nom = nom
            Me.prénom = prenom
        End Sub
     
        Public Overrides Function ToString() As String
            Return String.Format("{0} {1}", nom, prénom)
        End Function
    End Class
    En fait, dans le cas d'objet, les variables contiennent l'adresse de l'objet en mémoire (la notion de pointeur).

    Avec ByVal, on crée une copie de cette adresse dans une nouvelle variable
    Alors qu'avec ByRef, on prend l'adresse de la variable qui elle même contient l'adresse de l'objet.

    donc quand vous écrivez :
    Citation Envoyé par MABROUKI Voir le message
    2/ Le specificateur "byVal" n'a aucun effet dans ce cas...et toute modif de variable se repercute sur la variable initiale..............
    C'est toutes les variables contenues dans l'objet qui est modifiable, la variable contenant l'objet étant elle une copie, elle est modifiable mais la modification (le nouvel objet) ne se répercute pas en dehors de la procédure.


    Petit détail qui a toute son importance

  8. #8
    Membre Expert
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Par défaut
    Citation Envoyé par MABROUKI Voir le message
    2/ les variables "complexes" savoir:tableau,object,structure sont passees d'autorite par adresse c.à.d byRef .
    Le specificateur "byVal" n'a aucun effet dans ce cas...et toute modif de variable se repercute sur la variable initiale..............
    C'est la une logique interne tant qu'on travaille en vb.net.....
    Je veux bien ne pas avoir l'explication la plus technique, mais il aurait peut-être fallu la lire, car avec l'exemple que je donne il était aisé de se rendre compte que ceci était faux.
    Après à tomlev d'avoir apporté plus d'éclaircissements concrets car il était également vrai que je ne maitrisais pas non plus parfaitement le sujet.

    Cordialement !

  9. #9
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    bonjour à tous

    Merci pour la correction concernant le type structure qui est effectivement un type valeur ,vu que je n'utilise jamais les structures....à cause des tableaux qui doivent necessairement les accompagner...

    - D'abord, il n'y a pas de notion de "types simples" et de "types complexes", il n'y a que des types valeur et des types référence. Et les structures sont des types valeur, qui ne sont sûrement pas passés par référence par défaut...
    Quand je dis "types simples" et "types complexes",ca n'est pas une invention personnelle ,je fais reference à cette rublique de msdn doc :
    Types de données élémentaires

    Types de données numériques
    Présente les types numériques intégraux et non intégraux.

    Types de données caractère Présente les types Char et String.

    Types de données divers
    Présente les types Boolean, Date et Object.

    Types de données composites
    Un type composite diffère du type de données de l'ensemble de ses composants. Par exemple, un tableau d'éléments Integer n'est pas du type de données Integer
    Types structure
    Types tableau
    Types classe

    Ensuite ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     Ensuite, la notion de passage par valeur ou de passage par référence est complètement décorrélée de la notion de type valeur ou type référence. Tous les types sont passés par valeur (ByVal) par défaut, y compris les types référence..
    Non je ne suis d'accord à 100% sur ca.Pour preuve j'ai Mr MSDN avec moi:

    L'exemple suivant illustre deux procédures qui acceptent une variable tableau et opèrent sur ses éléments. La procédure increase ajoute simplement la valeur 1 à chaque élément. La procédure replace assigne un nouveau tableau au paramètre a(), puis ajoute la valeur 1 à chaque élément.

    Le premier appel MsgBox affiche "After increase(n): 11, 21, 31, 41". Étant donné que le tableau n est un type référence, replace peut modifier ses membres, même si le mécanisme de passage est ByVal.

    Le deuxième appel MsgBox affiche "After replace(n): 101, 201, 301". Étant donné que ByRef est passé à n, replace peut modifier la variable n dans le code appelant et lui assigner un nouveau tableau. Étant donné que n est un type référence, replace peut également modifier ses membres.
    Le code qui l'accompage:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    Visual Basic  Copier le code 
    Dim n() As Long = {10, 20, 30, 40}
    Call increase(n)
    MsgBox("After increase(n): " & CStr(n(0)) & ", " & _
        CStr(n(1)) & ", " & CStr(n(2)) & ", " & CStr(n(3)))
    Call replace(n)
    MsgBox("After replace(n): " & CStr(n(0)) & ", " & _
        CStr(n(1)) & ", " & CStr(n(2)) & ", " & CStr(n(3)))
     
     
    'Visual Basic  Copier le code 
    Public Sub increase(ByVal a() As Long)
        For j As Integer = 0 To UBound(a)
            a(j) = a(j) + 1
        Next j
    End Sub
    'Visual Basic  Copier le code 
    Public Sub replace(ByRef a() As Long)
        Dim k() As Long = {100, 200, 300}
        a = k
        For j As Integer = 0 To UBound(a)
            a(j) = a(j) + 1
        Next j
    End Sub
    Ce code est à mediter par -Sankass qui comprends les definitions d'une maniere lineaire pour ne pas dire simpliste- car ByVal permet de modifier les valeurs "composite" d'un type reference dans l'appelant................
    Mais cela illustre bien des subtilites de byval et de byref.
    Bonne relecture à tous....

  10. #10
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 540
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 540
    Par défaut
    Citation Envoyé par MoonlightSwamper Voir le message
    Voilà : dans les procédures évènementielles en VB, sender est une variable objet transmise par valeur. Or, les propriétés de l'objet désigné par sender sont accessibles en écriture, ce qui me semble a priori parfaitement contradictoire.
    je vais essayer de répondre à ta question
    1-la variable sender n'est modifiable que dans le corps de la procédure c'est pour cela qu'elle est passée par valeur

    2-ce n'est pas possible de raisonner avec des objets passés par référence parce que faut pas perdre de vue que .NET s'appuie essentiellement sur les fonctionnalités de Windows ( les API win32 ) sauf que c'est géré avec du "managed code".
    Pour créer une fenêtre en win32 tu vas appeler CreateWindowEx tu obtiens un handle de fenêtre un HWND et un "contexte" de dessin un HDC..
    or le problème c'est que ces objets ne sont pas toujours valides dans la durée de fonctionnement du programme et ils ne peuvent être modifiés que selon un certain "contexte" ( je suppose allocations mémoire de l'OS, gestion de la mémoire RAM, du tracé des fenêtres par le GDI).
    Si l'OS alloue un HWND de fenêtre il ne faut surtout pas que la procédure à laquelle est passée l'objet modifie le handle de fenêtre.
    Voilà pourquoi la durée de vie d'un objet dans une procédure n'est limité qu'à la procédure

+ Répondre à la discussion
Cette discussion est résolue.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo