C# Zuweisung / Referenzen

kiname

Cadet 3rd Year
Registriert
Nov. 2014
Beiträge
56
Hallo Community,

heute bin ich mal wider auf ein seltsames Problem gestoßen!
Recht viel erklären kann ich leider nicht es ist ein kurzer Quellcode.
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Testing
{
    class Program
    {
        static void Main(string[] args)
        {
            int zahl = 10;
            Test t = new Test() { wert = 7 };

            Aendern a = new Aendern(ref t);
            a.add(12);
            //t.wert ist jetzt 19
            Aendern2 b = new Aendern2(ref zahl);
            b.add(12);
            //zahl ist immer noch 10
        }
    }

    class Test
    {
        public int wert;
    }

    class Aendern
    {
        Test zahl;
        public Aendern(ref Test zahl)
        {
            this.zahl = zahl;
        }
        public void add(int wert)
        {
            this.zahl.wert += wert;
        }
    }
    class Aendern2
    {
        int zahl;
        public Aendern2(ref int zahl)
        {
            this.zahl = zahl;
        }
        public void add(int wert)
        {
            this.zahl += wert;
        }
    }
}
Warum wird der wert geändert wenn ich ein Objekt einer Klasse übergebe?
Warum wird der wert nicht geändert wenn ich einen normalen integer wert übergebe?

Ich habe mir dazu zusammengereimt, das es sein könnte, das bei der Zuweisung von einem Objekt einfach ein neuer Zeiger auf dem Objekt erstellt wird und bei primitiven Datentypen der wert kopiert wird aber warum ist das so?
Oder täusche ich mich bei dieser Erklärung?
Ich habe leider bis jetzt nichts gefunden das mir weiterhilft..

MFG
kiname
 
kiname schrieb:
Code:
            //zahl ist immer noch 10


Ist das dein "Problem"?

Mit Ändern arbeitest du ja mit wert von Test.
Bei Ändern2 arbeitest du mit zahl von Ändern2 und inkrementierst diese Variable und nicht int zahl aus deiner main.
 
Du hast es ziemlich genau erfasst: Wenn du ein Objekt als Parameter übergibst, dann entsteht dadurch keine neue, unabhängige Kopie des Objekts, sondern es wird nur eine neue Referenz auf das gleiche Objekt erzeugt.
 
Ja das ist mein Problem!

Die beiden Klassen Aendern und Aendern2 sind genau gleich aufgebaut der einzige unterschied ist der typ der Klassenvariable deshalb verstehe ich nicht wiso bei Aendern der wert in der main geändert wird und in Aendern2 nicht
 
Und bei den Primitiven Datentypen wird dann ein neues Objekt des Datentyps erstellt?
 
Vermutlich wird dieser Link (https://msdn.microsoft.com/en-us/library/14akc2c7.aspx) dir schon weiterhelfen.

Aber nochmal zur Verdeutlichung. Du musst zwischen value-Typen und reference-Typen unterscheiden. Zur ersten Kategorie gehören u.a.
  • int
  • double
  • string
  • struct
  • ...
Zur zweiten Kategorie gehört jeder der Typ, der über class (oder interface) definiert wird.

Rufst du nun eine Methode "normal" auf (kein ref), wird bei value-Typen tatsächlich der Wert übergeben, der dann in der Methode verwendet aber nicht an die aufrufende Instanz zurückgespielt werden kann. (Das ist das was dir bei deinem zweiten Aufruf passiert.)
reference-Typen werden nicht direkt übergeben, sondern nur deren Referenz. Somit werden auch Veränderung am Objekt selbst für die aufrufende Instanz sichtbar.

Ich hab mal an deinem Code rumgespielt.

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Testing
{
    class Program
    {
        static void Main(string[] args)
        {
            int zahl = 10;
            Test t = new Test() { wert = 7 };
 
            Aendern a = new Aendern(ref t);
            a.add(12);
            //t.wert ist jetzt 19
            Aendern2 b = new Aendern2(ref zahl);
            b.add(12);
            //zahl ist immer noch 10
        }
    }
 
    class Test
    {
        public int wert;
    }
 
    class Aendern
    {
        Test zahl;
        public Aendern(Test zahl) //genauso wirksam, da Referenzübergabe
        {
            this.zahl = zahl;
        }
        public void add(int wert) // der Wert im Objekt wird modifiziert
        {
            this.zahl.wert += wert;
        }
    }
    class Aendern2
    {
        int zahl;
        public Aendern2(int zahl) // gleicher Effekt da nur lesend auf den Wert zugegriffen wird
        {
            this.zahl = zahl;
        }
        public void add(int wert) // da Wertübergabe, keine Änderung nach außen sichtbar
        {
            this.zahl += wert;
        }
        public void addByRef(ref int wert) // passing by reference, nun wird die Änderung sichtbar
        {
            wert += this.zahl
        }       
    }
}
 
Zuletzt bearbeitet:
Zurück
Oben