Forum: PC-Programmierung C#: Objekt löschen


von Thomas_jhfd (Gast)


Lesenswert?

Hallo,

ich möchte so eine Struktur anlegen, wie z.B. in Interop Excel:
1
Excel.Worksheet worksheet = Application.Workbook.Worksheets.Add();
2
worksheet.Name = "Hallo";
3
4
foreach(Excel.Worksheet ws in Application.Workbook.Worksheets)
5
{
6
    System.Diagnostics.Debug.WriteLine(ws.Name);
7
}
8
9
Application.Workbook.Worksheets["Hallo"].Delete();
10
11
foreach(Excel.Worksheet ws in Application.Workbook.Worksheets)
12
{
13
    System.Diagnostics.Debug.WriteLine(ws.Name);
14
}

Die Struktur steht auch soweit, und foreach klappt nun auch durch 
Implementierung der Interfaces IEnumerator, IEnumerable.

Mein Problem ist das Delete().
Wie kann ich das umsetzten? Irgendwie muss ich ja das Objekt aus der 
Liste im Worksheets Objekt löschen.
Das Objekt kann sich ja nicht selbst löschen.
Das übernimmt dann wohl der Garbage Collector?

Gruß,
Thomas

von c-hater (Gast)


Lesenswert?

Thomas_jhfd schrieb:

> ich möchte so eine Struktur anlegen, wie z.B. in Interop Excel:
[...]
Das ist keine Struktur, sondern eine Liste.

> Mein Problem ist das Delete().
> Wie kann ich das umsetzten? Irgendwie muss ich ja das Objekt aus der
> Liste im Worksheets Objekt löschen.
> Das Objekt kann sich ja nicht selbst löschen.

Kann es schon. Es muß dazu nur wissen, dass es Element dieser speziellen 
Liste ist. Solange es nur eine Liste gibt, in der das Element enthalten 
sein kann, ist das auch ziemlich einfach zu lösen. Man schreibt halt 
einfach einen Konstruktor für das Element, bei dem auch ein Verweis auf 
die Liste übergeben wird.

Das funktioniert, ist aber unschön. In solchen Fällen ist es oft besser, 
das Erzeugen neuer Elemente ausschließlich durch die Liste vornehmen zu 
lassen. Sprich: die Elemente erhalten keine öffentlich zugreifbaren 
Konstruktoren, statt dessen erhält die Liste eine (oder mehrere) 
Factory-Methoden, die implizit die neuen Elemente erzeugen und dazu 
ihrereseits auf "private" Konstruktoren der Elemente zugreifen, über die 
dann der Verweis auf die Liste übergeben wird.

> Das übernimmt dann wohl der Garbage Collector?

Frühestens nach explizitem Löschen des Elementes aus der Liste kommt der 
GarbageCollector zum Zuge. So lange das Element existiert, stellt es 
eine Referenz auf das Objekt dar und der GarbageCollector darf 
referenzierte Objekte natürlich nicht löschen. Und aus irgendwelchen 
Listen (außer den eigenen) irgendwelche Elemente löschen, darf der 
GarbageCollector natürlich sowieso niemals.

von FS (Gast)


Lesenswert?

Was hat denn "Worksheets" für ein Datentyp? Wenn es ein 
Dictionary<Worksheet> ist, dann ist das entfernen doch einfach:
1
Worksheets.Remove("Hallo")

Listen o.ä. würde ich nicht selbst implementieren, die gibt es 
vorgefertigt in der .NET-Standardbibliothek.

von Thomas_jhfd (Gast)


Lesenswert?

Danke für die Antworten.

Ich habe es jetzt so gelöst:

* Die Worksheets Klasse hat folgende Methode bekommen:
public void Delete(string name)

* Der Konstruktor der Worksheet Klasse wurde erweitert, so dass das 
Objekt beim Anlegen durch Worksheets.Add() eine Referenz auf Worksheets 
speichert.

* Bei Worksheet.Delete() wird nun die oben angelegte Delete Methode im 
"Elternobjekt" aufgerufen, wo das Worksheet-Objekt aus der Liste 
entfernt wird.

Die Klassennamen sind bei mir anders.
Mir gefällt nur die Implementierung bei Excel Interop aus Anwendersicht 
so gut, dass ich das bei mir auch so umsetzen möchte.

Laut API-Referenz ist Worksheets eine Eigenschaft:
https://docs.microsoft.com/en-us/office/vba/api/excel.workbook.worksheets
Komisch, denn Worksheets entält ja auch die Methode Add().
Bei mir ist es auch ein Objekt, welches eine Liste von Worksheet als 
private Eigenschaft enthält:
private List<Worksheet> worksheets = new List<Worksheet>();
Bedienen lässt sich das nun genauso, wie im Code oben.

Alternativ hatte ich mir schon überlegt Worksheets von Dictionary zu 
erben und dann Methoden wie Add() zu überlagern:
class Worksheets : Dictionary<string, Worksheet>

Keine Ahnung, was besser ist. Ich arbeite mich noch ein...

von c-hater (Gast)


Lesenswert?

Thomas_jhfd schrieb:

> Ich habe es jetzt so gelöst:
[...]

OK, also die low-end-Lösung. Bezüglich der Isolation nicht optimal, aber 
geht.

> Mir gefällt nur die Implementierung bei Excel Interop aus Anwendersicht
> so gut, dass ich das bei mir auch so umsetzen möchte.
>
> Laut API-Referenz ist Worksheets eine Eigenschaft:
> https://docs.microsoft.com/en-us/office/vba/api/excel.workbook.worksheets
> Komisch, denn Worksheets entält ja auch die Methode Add().

Du solltest dir keinesfalls diesen Office-Kram zum Vorbild für neuen 
Code nehmen. Da werkelt ganz viel Code, der die alten COM-Konzepte mit 
DotNet (mehr oder weniger notdürftig) verheiratet. Da wird getrickst und 
getäuscht ohne Ende. Als unerfahrener Programierer hast du praktisch 
keine Chance, zu durchschauen, was da wirklich passiert.

Das ist aber auch überhaupt nicht nötig. So wie ich dich verstanden 
habe, willst du ja garnicht wirklich mit Office interagieren, sondern 
was Eigenes programmieren, was sich nur so ähnlich benutzen läßt, wie 
das Objektmodell von MS-Office. Und das kannst du tatsächlich tun. Sogar 
ziemlich problemlos. In DotNet sind nämlich auch die Erfahrungen 
eingeflossen, die Microsoft mit dem Objektmodell von MS-Office gesammelt 
hat (naja, nicht ganz uneigennützig sicherlich). Das Potential ist also 
in vollem Umfang vorhanden, du musst nur lernen, es zu nutzen.

von Thomas_jhfd (Gast)


Lesenswert?

> So wie ich dich verstanden habe, willst du ja garnicht wirklich mit
> Office interagieren, sondern was Eigenes programmieren, was sich nur
> so ähnlich benutzen läßt, wie das Objektmodell von MS-Office.

Richtig.
Ich ich schreibe eine Klassenbibliothek, der Anwender ist für mich also 
ein Programmierer.

So sieht es aus:
1
OptionHandler optionHandler = new OptionHandler(project);
2
3
optionHandler.Variants.Add("Standard");
4
optionHandler.Variants.Add("Pro");
5
optionHandler.Variants.Add("Premium");
6
optionHandler.Variants.Add("Test");
7
8
optionHandler.Variants["Pro"].Options.Add["Fehlersimulation"];
9
10
optionHandler.Variants["Premium"].Options.Add["Fehlersimulation"];
11
optionHandler.Variants["Premium"].Options.Add["Ruhestrommessung"];
12
13
optionHandler.Variants["Test"].Delete();
14
15
foreach(Variant variant in optionHandler.Variants)
16
{
17
    System.Diagnostics.Debug.WriteLine(variant.Name);
18
}
19
20
OptionHandler.ActiveVariant = "Premium";

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.