Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Dictionary Value Referenz Null setzen
Unfug
myCSharp.de - Member



Dabei seit:
Beiträge: 126

Themenstarter:

Dictionary Value Referenz Null setzen

beantworten | zitieren | melden

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
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Unfug am .
private Nachricht | Beiträge des Benutzers
dannoe
myCSharp.de - Member



Dabei seit:
Beiträge: 190

beantworten | zitieren | melden

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.
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von dannoe am .
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 1919
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
Unfug
myCSharp.de - Member



Dabei seit:
Beiträge: 126

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16223

beantworten | zitieren | melden

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.
Zitat von T-Virus
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.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Unfug
myCSharp.de - Member



Dabei seit:
Beiträge: 126

Themenstarter:

beantworten | zitieren | melden

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.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Unfug am .
private Nachricht | Beiträge des Benutzers
c#arp
myCSharp.de - Member



Dabei seit:
Beiträge: 10
Herkunft: Mannheim

beantworten | zitieren | melden

@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.
private Nachricht | Beiträge des Benutzers