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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
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";

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.