Excel Forum - Porady, Pomoc,  Excel Help, Excel FAQ Strona Główna
 FAQ  RegulaminRegulamin  Szukaj   Użytkownicy   Grupy   Rejestracja   Profil   Twoje wiadomości   Zaloguj 


Poprzedni temat «» Następny temat
ID tematu: 71056 Skopiuj do schowka ByVal, ByRef - raz jeszcze
Autor Wiadomość
Rafał B.
Stały bywalec Excelforum



Wersja: Win Office 2016
Pomógł: 48 razy
Posty: 342
Wysłany: 26-06-2021, 13:54   ByVal, ByRef - raz jeszcze

Już dużo tu było na forum na temat przekazywania parametrów do procedur i funkcji. Natomiast ze zdziwieniem w ostatnim czasie obserwuję wysyp nowych specjalistów ;-) VBA, powtarzających bez zrozumienia slogan, że zastosowanie słów kluczowych ByVal, ByRef w odniesieniu do przekazywanych obiektów nie ma żadnego znaczenia. Oczywiście najczęściej nie ma, ale nie zawsze. Jak zobaczycie takiego delikwenta zamiast tłumaczyć różnice między przekazaniem obiektu a przekazaniem wskaźnika / kopii wskaźnika do obiektu (a właśnie to drugie następuje w tej sytuacji), możecie go odwołać bezpośrednio do tego wątku. Napisałem może trochę "głupawy" przykład, ale obrazujący o co chodzi z możliwą ochroną/modyfikacją wskaźnika przez podprocedurę. Nie ma za co! :-)

Kod:
Public Sub Test()
   
    Dim coll As VBA.Collection
   
  ' ByRef.
    Set coll = New VBA.Collection
        coll.Add 10
       
    Debug.Print ">> ByRef test"
    Debug.Print "   Before: "; coll(1)
    TryByRef coll
    Debug.Print "   After: "; coll(1)
    Debug.Print
   
  ' ByVal.
    Set coll = New VBA.Collection
        coll.Add 10
       
    Debug.Print ">> ByVal test"
    Debug.Print "   Before: "; coll(1)
    TryByVal coll
    Debug.Print "   After: "; coll(1)
    End Sub
    ' -------------------------------------------------------------*


Private Sub TryByRef(ByRef coll As VBA.Collection)
   
    Dim anotherColl As New VBA.Collection
        anotherColl.Add 99
       
    Set coll = anotherColl
    End Sub
    ' -------------------------------------------------------------*
   
   
Private Sub TryByVal(ByVal coll As VBA.Collection)
   
    Dim anotherColl As New VBA.Collection
        anotherColl.Add 99
       
    Set coll = anotherColl
    End Sub
    ' -------------------------------------------------------------*


Immediate:
Kod:
>> ByRef test
   Before:  10
   After:  99

>> ByVal test
   Before:  10
   After:  10


(Nie wiem czy dział odpowiedni, jak coś, to proszę PT Moderację o przeniesienie.)
_________________
Abstrahując od języka: główną przyczyną niesławnego marnego poziomu jest prawdziwość wstydliwego stereotypu, że statystyczny programista VBA od ćwierć wieku czyta jedynie kod innych programistów dialektów Visual Basic.
ID posta: 406437 Skopiuj do schowka
 
 
Maciej Gonet 
Excel Expert


Wersja: Win Office 365
Pomógł: 2383 razy
Posty: 7331
Wysłany: 27-06-2021, 14:38   

Nieporozumienia wynikają chyba stąd, że procedura może wykonywać zmiany wewnątrz obiektu (na jego składowych) i takie zmiany są trwałe, niezależnie od sposobu przekazania obiektu (przez wartość czy przez odwołanie), a może również przypisać do zmiennej obiektowej inny egzemplarz obiektu - wtedy nowe przypisanie ma znaczenie lokalne, jeśli parametr był przekazany przez wartość, a jest trwałe - jeśli parametr był przekazany przez odwołanie.
Przykład, który podałeś dotyczy tego drugiego przypadku.
Można jednak podać inny podobny przykład, w którym będziemy odwoływać się zawsze do tego samego obiektu i tylko go modyfikować.
Kod:
Public Sub Test1()
   
    Dim coll As VBA.Collection
   
  ' ByRef.
    Set coll = New VBA.Collection
        coll.Add 10
       
    Debug.Print ">> ByRef test"
    Debug.Print "   Before: "; coll(1)
    Debug.Print ObjPtr(coll)
    TryByRef1 coll
    Debug.Print "   After: "; coll(2)
    Debug.Print
   
  ' ByVal.
    Set coll = New VBA.Collection
        coll.Add 10
       
    Debug.Print ">> ByVal test"
    Debug.Print "   Before: "; coll(1)
    Debug.Print ObjPtr(coll)
    TryByVal1 coll
    Debug.Print "   After: "; coll(2)
    End Sub
    ' -------------------------------------------------------------*

Private Sub TryByRef1(ByRef coll As VBA.Collection)
   
    coll.Add 99
    Debug.Print ObjPtr(coll)
    End Sub
    ' -------------------------------------------------------------*
   
Private Sub TryByVal1(ByVal coll As VBA.Collection)
   
    coll.Add 99
    Debug.Print ObjPtr(coll)
    End Sub
    ' -------------------------------------------------------------*


W tym drugim przykładzie nie ma znaczenia w jaki sposób wywołujemy obiekt w procedurze. W obu przypadkach dokonujemy zmian na tym samym obiekcie i jest on dostępny na zewnątrz procedury w takim samym stanie, niezależnie od sposobu przekazania obiektu do procedury.
ID posta: 406455 Skopiuj do schowka
 
 
Rafał B.
Stały bywalec Excelforum



Wersja: Win Office 2016
Pomógł: 48 razy
Posty: 342
Wysłany: 27-06-2021, 20:42   

Jak zawsze z naukowym sznytem w czytelny sposób Kolega zwerbalizował w jednym zdaniu to, na co potrzebowałem całego postu z podaniem przykładu. Chapeau bas!
_________________
Abstrahując od języka: główną przyczyną niesławnego marnego poziomu jest prawdziwość wstydliwego stereotypu, że statystyczny programista VBA od ćwierć wieku czyta jedynie kod innych programistów dialektów Visual Basic.
ID posta: 406462 Skopiuj do schowka
 
 
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Nie możesz załączać plików na tym forum
Możesz ściągać załączniki na tym forum
Dodaj temat do Ulubionych
Wersja do druku

Skocz do:  

Powered by phpBB modified by Przemo © 2003 phpBB Group
Theme xandgreen created by spleen& Programosy modified v0.3 by warna
Opieka techniczna www.wip.pl

Archiwum

Strona używa plików cookies.

Kliknij tutaj, żeby dowiedzieć się jaki jest cel używania cookies oraz jak zmienić ustawienia cookie w przeglądarce.
Korzystając ze strony użytkownik wyraża zgodę na używanie plików cookies, zgodnie z bieżącymi ustawieniami przeglądarki.
Sprawdź, w jaki sposób przetwarzamy dane osobowe