none
Parameterübergabe ByRef verhält sich anders als ref in C#? RRS feed

  • Frage

  • Ich arbeite Gerade an einem Projekt mit, in dem Libraries teilweise in VB.Net und C# erstellt wurden.

    In VB.Net habe ich jetzt ein Verhalten, dass ich so aus C# nicht kenne.
    Zur Verdeutlichung einige Zeilen zur Demonstration.

    Private w As Integer = 5
    
     Private Sub AufrufendeFunktion()
            incrementW(w)
            Debug.Print("Aufrufende Funktion: " + w.ToString())
        End Sub
    
    
     Private sub incrementW (ByRef intVar As Integer)
            intVar += 1
            Debug.Print("Variable  intVar in Funktion: " + i.ToString())
            Debug.Print("Private Variable w Funktion: " + w.ToString())
        End sub


    Als Ergebnis wird nun folgendes Ausgegeben:

    Variable  intVar in Funktion: 6
    Private Variable  w in Funktion: 5
    Aufrufende Funktion: 6

    Das Ergebnis ist für mich sehr überraschend und meines Erachtens falsch. Da die Variabele w ja ByRef übergeben wurde, müsste sich eine Änderung in der Funktion IncrementW auch direkt auf den Wert der Variablen auswirken. Dies ist aber nicht der Fall. Dieses Verhalten widerspricht all meinem Erwartungen einer Parameterübergabe per Referenz.

    In C# funktioniert die Referenzübergabe wie erwartet.


    private int w = 5;
    
     private void AufrufendeFunktion()
            {
                Increment(ref w);
                Debug.Print("Variable  myvar nach Funktion: " + w.ToString());
            }
    
    private void Increment(ref int intVar)
            {
                cIntVar++;
                Debug.Print("Variable  intVar in Funktion: " + cIntVar.ToString());
                Debug.Print("Variable  m in Funktion: " + w.ToString());
           }


    Hier in C# ist die Ausgabe dann entsprechend meinen Erwartungen.

    Variable  cIntVar in Funktion: 6
    Variable  w in Funktion: 6
    Variable  w nach Funktion: 6

    Wenn man aber statt einem WerteTyp per ByRef eine Klasse übergibt und in der Klasse eine Property ändert, dann funktioniert es auch in Vb.NET

    Public Class TestClass
        Public Property w as Integer = 5
    End Class
    
    Private c As  TestClass = new TestClass()
     Private sub AufrufendeFunktion()
            incrementK2(c)
            Debug.Print("Aufrufende Funktion: " + c.w.ToString())
        End sub
    
    Private sub incrementK2 ( i As TestClass)
            i.w += 1
            Debug.Print("Variable  w in Parameter in Funktion: " + i.w.ToString())
            Debug.Print("Variable  w  in Klasse in Funktion: " + c.w.ToString())
        End sub
    
    


    Jetzt kommt das Ergebnis auch wie erwarte.

    Variable  w in Parameter in Funktion: 6
    Variable  w  in Klasse in Funktion: 6
    Aufrufende Funktion: 6

    Gibt es für dieses in meinen Augen ungewöhliche Verhalten in VB.NET eine Erklärung oder muss man in VB.NET einfach mit ungewöhnlichen Verhalten rechnen.

    Gibt es noch andere unterschiedliche Verhaltensweisen auf die ich mich einstellen muss?

    Schöne Grüße aus dem HomeOffice

    Günter Schmid

    Freitag, 20. März 2020 17:28

Antworten

  • Hi Günter,
    in deinem Code ist ein Fehler:

     Private sub incrementW (ByRef intVar As Integer)
            intVar += 1
            Debug.Print("Variable  intVar in Funktion: " + i.ToString())
            Debug.Print("Private Variable w Funktion: " + w.ToString())
        End sub

    Was soll die Variable "i" sein?

    Bei mir kommt das erwartete Ergebnis in der folgenden Konsolenanwendung:

    Module Module39
    
      Sub Main()
        Try
          Dim c As New Demo
          c.Execute()
        Catch ex As Exception
          Console.WriteLine(ex.ToString)
        End Try
        Console.WriteLine("Continue enter key")
        Console.ReadKey()
      End Sub
    
      Friend Class Demo
        Private w As Integer = 5
    
        Friend Sub Execute()
          incrementW(w)
          Console.WriteLine("Aufrufende Funktion: " + w.ToString())
        End Sub
    
        Private Sub incrementW(ByRef intVar As Integer)
          intVar += 1
          Console.WriteLine("Variable intVar in Funktion: " + intVar.ToString())
          Console.WriteLine("Private Variable w Funktion: " + w.ToString())
        End Sub
      End Class
    
    End Module

    Ergebnis:

    Variable intVar in Funktion: 6
    Private Variable w Funktion: 6
    Aufrufende Funktion: 6
    Continue enter key


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Freitag, 20. März 2020 17:45

Alle Antworten

  • Hi Günter,
    in deinem Code ist ein Fehler:

     Private sub incrementW (ByRef intVar As Integer)
            intVar += 1
            Debug.Print("Variable  intVar in Funktion: " + i.ToString())
            Debug.Print("Private Variable w Funktion: " + w.ToString())
        End sub

    Was soll die Variable "i" sein?

    Bei mir kommt das erwartete Ergebnis in der folgenden Konsolenanwendung:

    Module Module39
    
      Sub Main()
        Try
          Dim c As New Demo
          c.Execute()
        Catch ex As Exception
          Console.WriteLine(ex.ToString)
        End Try
        Console.WriteLine("Continue enter key")
        Console.ReadKey()
      End Sub
    
      Friend Class Demo
        Private w As Integer = 5
    
        Friend Sub Execute()
          incrementW(w)
          Console.WriteLine("Aufrufende Funktion: " + w.ToString())
        End Sub
    
        Private Sub incrementW(ByRef intVar As Integer)
          intVar += 1
          Console.WriteLine("Variable intVar in Funktion: " + intVar.ToString())
          Console.WriteLine("Private Variable w Funktion: " + w.ToString())
        End Sub
      End Class
    
    End Module

    Ergebnis:

    Variable intVar in Funktion: 6
    Private Variable w Funktion: 6
    Aufrufende Funktion: 6
    Continue enter key


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Freitag, 20. März 2020 17:45
  • Hallo  Peter,

    danke für die schnelle Antwort.  Die Variable in meinem Beispiel sollte natürlich intVar lauten.

    Dein Beispiel mit der Konsolenanwendung funktioniert bei mir auch einwandfrei.

    Anscheinend war ich Freitag Abend schon etwas überarbeitet. Sonst hätte ich da schon am Freitag einfach einmal die Lösung bei unerklärlichen Fällen ausprobiert.
    Quellcode löschen und neu tippen.

    Kaum waren die paar Zeilen neu eingegeben kommt auch bei meiner Lösung das erwartete Ergebnis.

    Was immer auch das Visual Studio gedacht hat hier ausführen zu müssen.

    Viele Grüße aus dem Homeoffice

    Günter Schmid

    Montag, 23. März 2020 09:24