Przekazywanie argumentów według wartości i według odwołania (Visual Basic)

W języku Visual Basic można przekazać argument do procedury według wartości lub odwołania. Jest to nazywane mechanizmem przekazywania i określa, czy procedura może zmodyfikować element programowania będący podstawą argumentu w kodzie wywołującym. Deklaracja procedury określa mechanizm przekazywania dla każdego parametru, określając słowo kluczowe ByVal lub ByRef .

Wyróżnienia

Podczas przekazywania argumentu do procedury należy pamiętać o kilku różnych różnicach, które współdziałają ze sobą:

  • Czy bazowy element programowania jest modyfikowalny, czy niemodyfikowalny

  • Czy sam argument jest modyfikowalny, czy niemodyfikowalny

  • Czy argument jest przekazywany przez wartość, czy przez odwołanie

  • Czy typ danych argumentu jest typem wartości, czy typem odwołania

Aby uzyskać więcej informacji, zobacz Różnice między modyfikowalnymi i niemodyfikowalnymi argumentami i różnicami między przekazywaniem argumentu według wartości i przez odwołanie.

Wybór mechanizmu przekazywania

Należy dokładnie wybrać mechanizm przekazywania dla każdego argumentu.

  • Ochrona. Wybierając między dwoma mechanizmami przekazywania, najważniejszym kryterium jest narażenie zmiennych wywołujących na zmianę. Zaletą przekazania argumentu ByRef jest to, że procedura może zwrócić wartość do kodu wywołującego za pomocą tego argumentu. Zaletą przekazywania argumentu ByVal jest to, że chroni zmienną przed zmianą przez procedurę.

  • Wydajność. Mimo że mechanizm przekazywania może mieć wpływ na wydajność kodu, różnica jest zwykle nieznaczna. Jednym z wyjątków jest przekazany ByValtyp wartości . W tym przypadku program Visual Basic kopiuje całą zawartość danych argumentu. W związku z tym w przypadku dużego typu wartości, takiego jak struktura, bardziej wydajne może być przekazanie go ByRef.

    W przypadku typów referencyjnych tylko wskaźnik do danych jest kopiowany (cztery bajty na platformach 32-bitowych, osiem bajtów na platformach 64-bitowych). W związku z tym można przekazać argumenty typu String lub Object według wartości bez szkody dla wydajności.

Określanie mechanizmu przekazywania

Deklaracja procedury określa mechanizm przekazywania dla każdego parametru. Kod wywołujący nie może zastąpić ByVal mechanizmu.

Jeśli parametr jest zadeklarowany za pomocą ByRefmetody , kod wywołujący może wymusić użycie mechanizmu ByVal przez dołączenie nazwy argumentu w nawiasach w wywołaniu . Aby uzyskać więcej informacji, zobacz How to: Force an Argument to Be Passed by Value (Instrukcje: wymuszanie przekazania argumentu według wartości).

Wartością domyślną w języku Visual Basic jest przekazywanie argumentów według wartości.

Kiedy przekazać argument według wartości

  • Jeśli element kodu wywołującego będący podstawą argumentu jest elementem niemodyfikowalnym, zadeklaruj odpowiedni parametr ByVal. Żaden kod nie może zmienić wartości elementu niemodyfikowalnego.

  • Jeśli element bazowy jest modyfikowalny, ale nie chcesz, aby procedura mogła zmienić jego wartość, zadeklaruj parametr ByVal. Tylko kod wywołujący może zmienić wartość modyfikowalnego elementu przekazanego przez wartość.

Kiedy przekazać argument według odwołania

  • Jeśli procedura ma rzeczywistą potrzebę zmiany podstawowego elementu w kodzie wywołującym, zadeklaruj odpowiedni parametr ByRef.

  • Jeśli poprawne wykonanie kodu zależy od procedury zmiany podstawowego elementu w kodzie wywołującym, zadeklaruj parametr ByRef. Jeśli przekazujesz go według wartości lub jeśli kod wywołujący zastępuje ByRef mechanizm przekazywania przez dołączenie argumentu w nawiasach, wywołanie procedury może spowodować nieoczekiwane wyniki.

Przykład

opis

Poniższy przykład ilustruje, kiedy przekazać argumenty według wartości i kiedy przekazać je według odwołania. Procedura Calculate ma parametr i ByValByRef . Biorąc pod uwagę stopę procentową, ratei sumę pieniędzy, debtzadaniem procedury jest obliczenie nowej wartości debt , która jest wynikiem zastosowania stopy procentowej do pierwotnej wartości debt. Ponieważ debt jest parametremByRef, nowa suma jest odzwierciedlana w wartości argumentu w kodzie wywołującym, który odpowiada .debt Parametr rate jest parametrem ByVal , ponieważ Calculate nie powinien zmieniać jego wartości.

Kod

Module Module1

    Sub Main()
        ' Two interest rates are declared, one a constant and one a 
        ' variable.
        Const highRate As Double = 12.5
        Dim lowRate = highRate * 0.6

        Dim initialDebt = 4999.99
        ' Make a copy of the original value of the debt.
        Dim debtWithInterest = initialDebt

        ' Calculate the total debt with the high interest rate applied.
        ' Argument highRate is a constant, which is appropriate for a 
        ' ByVal parameter. Argument debtWithInterest must be a variable
        ' because the procedure will change its value to the calculated
        ' total with interest applied.
        Calculate(highRate, debtWithInterest)
        ' Format the result to represent currency, and display it.
        Dim debtString = Format(debtWithInterest, "C")
        Console.WriteLine("What I owe with high interest: " & debtString)

        ' Repeat the process with lowRate. Argument lowRate is not a 
        ' constant, but the ByVal parameter protects it from accidental
        ' or intentional change by the procedure. 

        ' Set debtWithInterest back to the original value.
        debtWithInterest = initialDebt
        Calculate(lowRate, debtWithInterest)
        debtString = Format(debtWithInterest, "C")
        Console.WriteLine("What I owe with low interest:  " & debtString)
    End Sub

    ' Parameter rate is a ByVal parameter because the procedure should
    ' not change the value of the corresponding argument in the 
    ' calling code. 

    ' The calculated value of the debt parameter, however, should be
    ' reflected in the value of the corresponding argument in the 
    ' calling code. Therefore, it must be declared ByRef. 
    Sub Calculate(ByVal rate As Double, ByRef debt As Double)
        debt = debt + (debt * rate / 100)
    End Sub

End Module

Zobacz też