Laden...

Dictionary Value Referenz Null setzen

Erstellt von Unfug vor 2 Jahren Letzter Beitrag vor 2 Jahren 364 Views
U
Unfug Themenstarter:in
133 Beiträge seit 2006
vor 2 Jahren
Dictionary Value Referenz Null setzen

Hallo zusammen,

ich stehe derzeit auf dem Schlauch und hoffe, dass Ihr mir weiterhelfen könnt. Hab eine Denkblockade.

Ich füge als Value eines Dictionary ein Objekt der Klasse TestClass hinzu.
Im weiteren Verlauf setze ich dieses Objekt auf null.
Im Dictionary ist jedoch die Kopie?!/Referenz?! noch vorhanden. Ich dachte wegen Call by Referenz müsste das auch Null sein.
Geht das nicht beim Dictionary? Was wäre eine Alternative?


Dictionary<string, TestClass> list = new Dictionary<string, TestClass>();
TestClass? myclass = new();
list.Add("1", myclass);
myclass = null; //ab hier hätte ich gedacht, dass der Wert auch im Dictionary null ist.

list["1"].EineMethode(); // <<< wieso klappt das?

public class TestClass
{
	public string EineMethode()
	=> "Hello World";
}


Im echten Code übergebe ich keine TestClass, sondern Func<T,Task>.
Danke

D
261 Beiträge seit 2015
vor 2 Jahren

Call-by-Reference betrifft die Übergabe von Referenzen bzw. Werte an Methoden. (siehe ref keyword - C# Reference)
In deinem Beispiel erstellst du eine neue Instanz und setzt die Referenz auf diese Instanz in deiner lokalen Variable testClass.
Anschließend überschreibst du den Inhalt (nicht aber das Ziel der Referenz) der lokalen Variable mit "null".

Was gehen würde wäre das hier:


TestClass myclass = new();
SetVariableToNull(ref myclass);
// jetzt ist die Variable myclass auch null

public void SetVariableToNull(ref TestClass testClass)
{
   testClass = null;
}

Dein Dictionary würde trotzdem noch die Referenz auf die ursprüngliche Instanz halten.

T
2.224 Beiträge seit 2008
vor 2 Jahren

Hier wäre der Anwendungsfall mal interessant.
Mir ist nämlich nicht klar was der Zweck sein soll bzw. welchen Vorteil der Null Value haben soll.
Mit dem Ansatz eines Null Values müsstest du an allen Stellen, an denen du den Wert ausliest auch einen Null Check machen.
Das erhöht die Fehleranfälligkeit.

Sinnvoller wäre es, den Eintrag aus dem Dictionary zu entfernen wenn dieser nicht vorhanden sein soll.
Dann kannst du mit einem einfachen TryGetValue prüfen ob es einen passenden Eintrag gibt.
Wenn nicht, hast du die selbe Situation wie bei einem Null Eintrag.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

U
Unfug Themenstarter:in
133 Beiträge seit 2006
vor 2 Jahren

Danke. Ja natürlich..das mit der Referenz .. Kopf auf den Tisch hauen. Manchmal sollte man wirklich früher ins Bett.

T-Virus:
Die Idee dahinter ist Nutzung eines sehr einfachen Eventbus wie diesen hier:
https://github.com/mxjones/RedBus
Globale Events, sollen dazu führen, dass in den Objekten verschiedene Methoden ausgeführt werden.
Es sollen als Subscribe Object.Funktionen übergeben werden die aufgerufen werden sollen.
Wenn das Object zerstört wird, dass ein EventBus.Subscribe ausgeführt hat, soll das auch aus dem Dictionary gelöscht werden, damit kein Callback hier aufgerufen wird.

16.835 Beiträge seit 2008
vor 2 Jahren

Benutz doch bei solch einem Vorhaben, vor allem mit Shared Objects, was robustes wie zB. Reactive Extensions.
Nen Dict für sowas is auch wirklich keine gute Idee; in RX verwendet man da entsprechend Observable

Aus Architektursicht: global hält man eigentlich States, weniger Business Objekte.
D.h. die Methode sollte nicht am State Object liegen, was sich auch kaum richtig testen lässt.
Resultiert durchaus oft in Race Conditions, weil Du bei der Ausführung auf den State selbst nicht zugreifen kannst; das oft aber notwendig ist.

Sinnvoller wäre es, den Eintrag aus dem Dictionary zu entfernen wenn dieser nicht vorhanden sein soll.

Finds immer schwer irgendwas als sinnvoller zu bezeichnen, wenn man den Inhalt nicht kennt; hier ist die Funktionsweise völlig unklar.
Woher soll man wissen, dass das dann sinnvoller ist?

Generell: ein Null-Eintrag im State kann durchaus dazu dienen, dass ein reload reforced wird, zB. durch ein Invalidation-Mechanismus.

U
Unfug Themenstarter:in
133 Beiträge seit 2006
vor 2 Jahren

Guter Tipp. Habe mit Reactive Extensions noch nicht gearbeitet. Kann das jetzt mal als Einstieg nutzen.

Das mit dem Thema State vs Business Objekte kann ich 100% nachvollziehen.
Hatte nämlich genau das Problem bei den Tests.

Aufjedenfall vielen Dank an alle. Es gab viele Anregungen, die ich jetzt testen werde. 👍

C
9 Beiträge seit 2012
vor 2 Jahren

@Unfug
In .NET hast Du ja keinen direkten Einfluss aufs Speichermanagement. Referenztypen (also kurz Klassen oder Delegates) kannst Du nicht direkt aus dem Speicher entfernen, wenn Du sie auf null setzt. Die Laufzeitumgebung analysiert wie viele Referenzen existieren, wenn keine mehr existieren wird das Objekt _irgendwann _abgeräumt.
In Deinem Fall hast Du aber nur eine von zwei Referenzen entfernt. Dann wird das Objekt natürlich nicht abgeräumt. Die zweite Referenz entsteht durch das zuweisen des KeyValue-Paares im Dictionary.

In nicht verwalteter Umgebung kann man das Objekt direkt "abräumen", also den Speicher den es benötigt, wieder freigeben, in C++ mit delete.
Aber damit kann man auch viel Unsinn anstellen.