W Visual Basic parametry procedur mogą być przekazywane przez odniesienie (ByRef) lub przez wartość (ByVal). To ma wpływ na to, czy zmiany wewnątrz procedury będą miały odzwierciedlenie w zewnętrznej zmiennej.
Historia pytania:
Domyślnie w VB.NET parametry procedur są przekazywane przez wartość (ByVal), co oznacza przekazywanie kopii wartości. Przez ByRef przekazywana jest nie kopia, ale odniesienie do oryginalnej zmiennej.
Problem:
Użycie niepoprawnej metody przekazywania prowadzi do błędów — na przykład przy nieprawidłowym użyciu ByRef procedura może niezamierzenie zmieniać zmienne kodu wywołującego lub odwrotnie, zmiany nie będą zapisane.
Rozwiązanie:
ByRef używa się, gdy wymagane jest zwrócenie kilku wartości lub zmiana przekazanej zmiennej. ByVal — w pozostałych przypadkach w celu ochrony przed niepożądanymi zmianami. Wyjątkowo ważne jest, aby jasno wskazywać ByRef tylko w razie potrzeby.
Przykład przekazywania przez wartość i przez odniesienie:
Sub DoubleValue(ByVal x As Integer) x = x * 2 End Sub Sub DoubleValueByRef(ByRef x As Integer) x = x * 2 End Sub Dim a As Integer = 5 DoubleValue(a) ' a wciąż 5 DoubleValueByRef(a) ' a teraz wynosi 10
Kluczowe cechy:
Co się stanie z obiektem przy przekazywaniu przez ByRef: czy zmieni się odniesienie do obiektu?
Odpowiedź: Jeśli przekazywać obiekt przez ByRef i przypisać zmiennej wewnątrz procedury nowy obiekt, to oryginalna zmienna poza procedurą również będzie wskazywać na nowy obiekt. Jeśli przekazywać przez ByVal, można zmieniać właściwości obiektu, ale nie można przekierować samego odniesienia — zmienna poza procedurą pozostanie ta sama.
Sub ChangeRef(ByRef p As Person) p = New Person() With {.Name = "Inny"} End Sub Sub ChangeVal(ByVal p As Person) p.Name = "Zmienione" End Sub Dim pers As New Person With {.Name = "Oryginalny"} ChangeRef(pers) ' pers teraz nowy obiekt ChangeVal(pers) ' pers — ten sam obiekt, imię zmienione
Czy można użyć ByRef do zwrócenia wartości z funkcji?
Odpowiedź: Nie, ByRef określa się tylko przy przekazywaniu parametrów, a nie dla samej zwracanej wartości funkcji.
Co jeśli zadeklaruję argument tablicy z ByVal — czy można zmienić zawartość tablicy?
Odpowiedź: Tak, ponieważ w VB.NET tablica jest typem referencyjnym, i mimo że jest przekazywana przez ByVal, samo odniesienie jest kopiowane, a elementy tablicy (przez to samo odniesienie) można zmieniać wewnątrz procedury.
W zespole jeden z programistów użył ByRef w algorytmie przetwarzania, a zmiana wartości w jednej części programu niespodziewanie zmieniła stan zmiennej, przez co moduł przestał działać poprawnie.
Zalety: Pozwala zmieniać dane bez określania struktury zwracanego wyniku.
Wady: Wysokie ryzyko nieoczywistych efektów ubocznych, trudności w debugowaniu błędów.
Parametry są przekazywane przez ByVal, a zwracanie wielu wartości odbywa się poprzez zwracane struktury lub krotki, co czyni zachowanie jasno określonym i wygodnym.
Zalety: Łatwiej czytać i utrzymywać kod, mniej błędów.
Wady: Czasami trzeba tworzyć dodatkowe typy lub struktury.