Laden...

Arbeiten auf dem richtigen Objekt - Wie kann ich Referenzen in Methoden reichen?

Erstellt von Rabenrecht vor 6 Jahren Letzter Beitrag vor 6 Jahren 1.217 Views
R
Rabenrecht Themenstarter:in
5 Beiträge seit 2017
vor 6 Jahren
Arbeiten auf dem richtigen Objekt - Wie kann ich Referenzen in Methoden reichen?

Habe gerade erst mit C# angefangen und es haben sich einige Fragen ergeben.

Folgendes: Ich habe eine Klasse deren Instanzen in anderen Klassen/Methoden referenziert und ggf. auch geändert werden. Dabei habe ich zwei Anliegen:

  1. Ich würde gerne unnötige Kopien der Instanzen vermeiden.

  2. viel wichtiger: es muss sicher gestellt sein, dass Änderungen an der richtigen Instanz (und nicht etwa einer lokalen Kopie) vorgenommen werden.

Eigentlich eine ganz grundlegende Programmierthematik.

In C++ würde ich das ganz einfach über Pointer regeln, aber in C# müsste man seinen Code dazu als "unsicher" deklarieren. Wie wäre denn der "saubere" Weg in C# das zu erreichen?

Beispiel:


public class Actor {
    public Condition condition;
    public int attribute = 0;
}

public class Condition {
   private Actor actor;

   public Condition(Actor actor)
   {
      this.actor = actor;
   }
   
   public void DoStuff()
   {
      actor.attribute = 42;
   }
}

public class Program {
   public void main()
   {
      Actor actor = new Actor();
      actor.condition = new Condition(actor);
      actor.condition.DoStuff();
      print(actor.attribute);
   }
}

Da würde dann 0 ausgegeben werden.

In C++ würde ich das so machen:


public class Actor {
    public Condition condition;
    public int attribute = 0;
}

public class Condition {
   private Actor* actor;

   public Condition(Actor* actor)
   {
      this.actor = actor;
   }
   
   public void DoStuff()
   {
      actor->attribute = 42;
   }
}

public class Program {
   public void main()
   {
      Actor actor = new Actor();
      actor.condition = new Condition(&actor);
      actor.condition.DoStuff();
      print(actor.attribute);
   }
}

(oder so ähnlich; mein C++ ist etwas eingerostet)
Ich würde genau eine actor Instanz erzeugen und der condition eine Referenz darauf mitgeben.

Wie geht sowas in C#?

Mir ist der Parameteraufruf mit ref bekannt. Darüber kann ich in einer Methode mit der Referenz arbeiten. Die Referenz aber zu speichern geht, soweit ich das sehe, nicht.

2.207 Beiträge seit 2011
vor 6 Jahren

Hallo Rabenrecht,

ref-Parameter sieht man eher selten. Schau dir mal Referenz- und Wertetypen an. Wenn du mit new() ein Objekt erzeugst und dieses Objekt in eine Methode reichst, dann reichst du eine Referenz in die Methode. Du machst ja kein zweites new() irgendwo.

Da würde dann 0 ausgegeben werden.

In deinem Codebeispiel kommt da in C# "42" raus 😃

Tanzt du auf den Properties des Objektes rum, werden die Properties des Objekts verändert. Keine Kopie oder ähnliches.

Gruss

Coffeebean

R
Rabenrecht Themenstarter:in
5 Beiträge seit 2017
vor 6 Jahren

Ok... jetzt fühl ich mich doof 😉

Offenbar behandelt C# primitive Typen anders als Objekte. Der obige C#-Code macht schon genau das, was ich will 😃

3.003 Beiträge seit 2006
vor 6 Jahren

Wie geht sowas in C#?

In sehr, sehr weiten Teilen intuitiv. Soll heißen: man muss sich weit weniger Gedanken über das Thema machen, als das in C++ der Fall ist. Man muss auch aufhören, innerlich das Wort "Pointer" zu benutzen.

Interessant wird es erst, wenn einem Methodenparameter innerhalb der Methode eine neue Referenz (mit new()) zugewiesen wird (was CoffeeBean angedeutet hat). Alles andere funktioniert so, wie man es erwarten würde, wenn man vorher noch nie etwas von Referenzen gehört hätte.

Soll heissen ein Wert, der einer Methode übergeben wurde und dessen Eigenschaften in dieser Methode manipuliert wurden, erhält die manipulierten Eigenschaften über den Scope der Methode hinaus.

Gut beschrieben hier: Übergeben von Parametern (C#-Programmierhandbuch)
...besonders relevant hier: Übergeben von Verweistypparametern (C#-Programmierhandbuch)

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

2.207 Beiträge seit 2011
vor 6 Jahren

Hallo zusammen,

haaach - genau die Links hatte ich gesucht. Danke 😉

Gruss

Coffeebean

1.029 Beiträge seit 2010
vor 6 Jahren

Hi,

du solltest dir C# mal komplett anschauen.

Grundlegend gibt man Variablen nicht nach außen frei - sondern kapselt diese in Properties.

Deine Actor-Klasse würde sich dann so gestalten:


public class Actor 
{
    public Condition Condition {get;set;}
    public int Attribute {get; set;}
} 

--> Die Klasse Condition dann äquivalent.

GGf. kann man sich an der Stelle auch überlegen der Klasse Actor beim Property Condition den Setter wegzunehmen und diese Instanz im Konstruktor der Actor-Klasse zu initialisieren - das verhindert Fehler in der Handhabung.

Dein "Problem" existiert der Gestalt wie du denkst wie bereits von den anderen beschrieben jedenfalls nicht.

LG

Edit:
Vorher beschriebene Schreibweise ist übrigens die Kurzform für:


public class Actor 
{
	private Condition _condition;
        public Condition Condition
	{
		get
		{
			return _condition;
		}
		set
		{
			_condition = value;
		}
	}
    
	private int _attribute;
	public int Attribute
	{
		get
		{
			return _attribute;
		}
		set
		{
			_attribute = value; 
		}
	}
} 

Ich denke du siehst direkt, was das für Möglichkeiten bietet 😉