Laden...

Objekt in generischer Liste finden

Erstellt von rzwanziger vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.289 Views
R
rzwanziger Themenstarter:in
73 Beiträge seit 2007
vor 15 Jahren
Objekt in generischer Liste finden

Hallo,

folgendes Problem: Ich habe eine Klasse "Person", welche einen Namen und ein Geburtstag aufnehmen soll:


  public class Person
  {
    private string name;

    public string Name
    {
      get { return name; }
    }

    private DateTime geboren;

    public DateTime Geboren
    {
      get { return geboren; }
    }

    public Person(string aName, DateTime aDate)
    {
      name = aName;
      geboren = aDate;
    }
  }

Weiterhin habe ich eine Liste, in die ich mittels Methode "Add" die Personen aufnehme:


   private List<Person> Personenliste = new List<Person>();
   ...
   private Person p;
   p = new Person("Hans", new DateTime(1980, 5, 15);
   Personenliste.Add(p);

Ich möchte nun ein neu erzeugtes Person-Objekt so in die Liste einfügen, dass:

  • es angefügt wird, wenn die Liste nicht bereits ein Objekt enthält, bei dem der Name gleich ist
  • ansonsten, wenn es ein Objekt mit gleichem Namen gibt, soll das Geburtsdatum dieses Objekts entsprechend auf das Geburtsdatum des übergebenen Objekts geändert werden (oder der Einfachheit halber: das gesamte Objekt ersetzt werden).

Lösen kann ich das Ganze, indem ich vor jedem Personenliste.Add() die gesamte Liste nach dem neuen Namen durchsuche und dann ggfls. ersetze oder eben anfüge.

Meine Frage ist: Gibt es da vielleicht eine elegantere Möglichkeit? Die generischen Listen haben doch eine Find<T>-Methode, aber die ganzen Beispiele mit predicate die ich gefunden habe, passen irgendwie nicht zum Problem der List<object>.

Danke für Anregungen,

Ralf

1.200 Beiträge seit 2007
vor 15 Jahren

Welche dotnet Version? LINQ wäre optimal für das, was du erreichen willst.

Ansonsten könntest auch einfach über die Liste iterieren und gucken, ob die Person schon drin ist. Dies wäre allerdings über ein Predicate schöner gelöst. Du brauchst ja quasi ein Predicate(Person p), da könntest du dann über die Find Methoden nach dem Namen suchen. Oder nach beliebigen Inhalten.

Shift to the left, shift to the right!
Pop up, push down, byte, byte, byte!

YARRRRRR!

Gelöschter Account
vor 15 Jahren
  1. passt die predicat-geschichte perfekt hier rein. zudem kannst du einfach eine anonyme methode reinschreiben (ist dann ein einzeiler).
  2. wäre hier auch ein dictionary von interesse Dictionary<string,DateTime>, dann hättest du viele probleme nicht mehr. oder du machst ein Dictionary<string,Person>
  3. evtl über die bindinglist<T> und an das add-event abbonieren. in diesem event hast du einige manipulationsgelegeneheiten.
F
10.010 Beiträge seit 2004
vor 15 Jahren

Das mit den Predicates ist nicht wirklich schwierig.

In C#2:


Person foundPerson = personList.Find( delegate(Person item){ return item.Name == gesuchterName;});

In C#3:


Person foundPerson = personList.Find( (x) => x.Name == gesuchterName );


if( foundPerson == null )
{
  foundPerson = new Person();
  foundPerson.Name=gesuchterName;
  personList.Add(foundPerson);
}

foundPerson.Geboren = ...

Allerdings würde sich ein Dictionary eher anbieten, bei dem du den namen als Key benutzt.

edit: war wohl jemand schneller.

R
rzwanziger Themenstarter:in
73 Beiträge seit 2007
vor 15 Jahren

Ja, genau so funktioniert's. Vielen Dank!!

Das mit dem Dictionary würde nicht gehen, da meine "Person" noch ein paar andere Parameter hat - die habe ich aber der Einfachheit halber in dem Beispiel weggelassen.

Danke,
Ralf

Gelöschter Account
vor 15 Jahren

Das mit dem Dictionary würde nicht gehen

doch würde gehen: Dictionary<string,Person>

S
469 Beiträge seit 2007
vor 15 Jahren

hmm, ich hätte das spontan so gelöst, dass ich in der Klasse Person die Equals Funktion überschreibe und darin die Namen der Personen vergleiche, und dann geguckt über die List.contains()-Funktion die ja das Equals verwendet, ob die Person schon drinsteckt, und sie falls nein hinzugefügt, falls ja ersetzt...

Die hier erwähnte Methode kannte ich noch nicht, ich nehm mal an die ist eleganter (wenn sie spontan auch etwas komplizierter (ungleich kompliziert) aussieht)?

gruß
sth_Weird

++++++++++++++++++++~+
Fluchen ist die einzige Sprache, die jeder Programmierer perfekt beherrscht


Linux is for free...if your time is worth nothing
++++++++++++++++++++~+

O
778 Beiträge seit 2007
vor 15 Jahren

Equals so zu überschreiben halte ich für eine schlechte Idee, weil man zwei Personen mit gleichem Namen dann nur noch mit Object.ReferenceEquals auseinanderhalten kann, was verdammt unintuitiv ist und damit Bugs heraufbeschwört.

S
469 Beiträge seit 2007
vor 15 Jahren

Equals so zu überschreiben halte ich für eine schlechte Idee, weil man zwei Personen mit gleichem Namen dann nur noch mit Object.ReferenceEquals auseinanderhalten kann, was verdammt unintuitiv ist und damit Bugs heraufbeschwört.

Stimmt...
Ich habe das mit dem equals schon oft gemacht, aber für meine Verwendung hat es jedes Mal gepasst...
Die hier vorgestellte Variante werd ich mir für die Zukunft merken!
Nur eine Frage noch, vielleicht kanns jemand schnell beantworten damit ich es nicht selbst mit einem Beispielprojekt ausprobieren muss...
Um nicht zu arg vom Thema abzuschweifen greife ich die Klasse Person des OP auf (und vielleicht hat er ja auch mal das gleiche oder ähnliche Problem)...man hat eine Liste mit Personen, die ich als Items einer ComboBox setze. Wie selektiere ich nun eine bestimmte Person?
Mit meiner equals Variante muss ich nur sagen SelectedItem = meinePerson, egal ob die Referenz gleich ist oder nicht, der Eintrag wird richtig selektiert, weil intern die equals Funktion verwendet wird um die Objekte zu vergleichen (? hab ich so gelesen und in meinen Anwendungen hat's so auch immer funktioniert).
Ohne equals zu überschreiben würde es nur funktionieren wenn die Referenzen wirklich identisch sind...wie würde man die Selektion einer Person in der ComboBox hier am elegantesten und vor allem für den Anwender schnellsten vornehmen?

thx
sth_Weird

++++++++++++++++++++~+
Fluchen ist die einzige Sprache, die jeder Programmierer perfekt beherrscht


Linux is for free...if your time is worth nothing
++++++++++++++++++++~+

Gelöschter Account
vor 15 Jahren

@sth_Weird

ich weiß jetzt nicht wirklich worauf du hinaus willst. das selektieren geschieht exakt so wie in deiner version. "SelectedItem = meinePerson" natürlich darf meinePerson nicht ein neue instanz sein sondern muss schon eine bereits vorhandesne instanz innerhalb der comboboxitems sein.

J
1.114 Beiträge seit 2007
vor 15 Jahren

Ohne equals zu überschreiben würde es nur funktionieren wenn die Referenzen wirklich identisch sind...wie würde man die Selektion einer Person in der ComboBox hier am elegantesten und vor allem für den Anwender schnellsten vornehmen?

Für solche Fälle überschreibe ich einfach die ToString() Methode der Person-Klasse und füge die Person Instanz direkt in die Items Liste der Combobox ein... Danach kannst du dann direkt über die SelectedItem der Combobox auf dein ursprüngliches Person Objekt casten.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo sth_Weird,

Um nicht zu arg vom Thema abzuschweifen

hast du schon alleine gemacht, weil du ComboBox ins Spiel gebracht hast, wir hier aber in Basistechnologien sind. Also bitte hier nicht weiter ins Detail gehen.

herbivore