Laden...

Wie 2 ähnliche Methoden zusammenfassen?

Erstellt von Froggie vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.739 Views
F
Froggie Themenstarter:in
323 Beiträge seit 2007
vor 15 Jahren
Wie 2 ähnliche Methoden zusammenfassen?

Der Gedanke von OOP ist ja so wenig redundanten Code wie möglich zu haben.
Nun habe ich folgendes Szenario:
Es gibt eine Liste mit Personen vom Typ A und vom Typ B (beide in zufälliger Reihenfolge in der selben Liste). Nun habe ich eine Eigenschaft welche mir nur die Personen eines bestimmten Typs zurückliefert und gleichzeitig einige Filter (weitere Eigenschaften der Personen) anwendet.
Diese Eigenschaft gibt es zwei mal (einmal für Typ A und einmal für Typ B) und der Code ist mittlerweile auf 400 Zeilen angewachsen. Die beiden Eigenschaften unterscheiden sich nur minimal:
z.B. beim hinzufügen einer Liste: in einer Eigenschaft wird die Liste für Typ A verwendet in der anderen Eigenschaft die Liste für Typ B

public Person AllPersonsTypA
{
  ...
  listA.Add(tmpPerson);
  ...
}

public Person AllPersonsTypB
{
  ...
  listB.Add(tmpPerson);
  ...
}

Wie kann ich diese beiden Eigenschaften rationalisieren? Nur noch eine Methode mit einem Parameter welcher Typ das ist und dann jedesmal eine if-Abfrage welche Liste verwendet werden soll?

Es ist wirklich ein Graus wenn es eine Änderung gibt müssen beide Eigenschaften angepasst werden und dabei vergisst man schon mal was.

PS: .Net 2.0

Vielen Dank im Vorraus!

F
240 Beiträge seit 2006
vor 15 Jahren


public IList<Person> PersonsByType(var filter) // musste hier selber sehen 
{
  List<Person> output = new List<Person>();
  foreach (Person p in list)
  {
    if(p.FilterProp == filter)
    output.Add(p);
  }
   return output;
}

So würd ichs machen, lasse mich aber gerne über eine bessere Methode belehren (in C# 3.5 und .net 3.5 würd ichs mit Linq machen)

691 Beiträge seit 2007
vor 15 Jahren

Moin.

Also so wie ich das sehe, bräuchtest du dann schon eine Methode, der du einen Typ übergibst. Um die Anzahl der verwendeten Typen dynamisch zu halten, könntest du deine Listen (listA, listB etc) in ein Dictionary vom Typ <type, List> speichern. Dann weiß deine Methode auch welche List sie bearbeiten soll.

Zusätzlich schau dir mal Generische Eigenschaft erstellen, deren Typ erst zur Laufzeit bekannt wird an

mit freundlichen Grüßen,
Tomot

Projekte: www.gesellschaftsspieler-gesucht.de

O
778 Beiträge seit 2007
vor 15 Jahren

Also mir fehlen noch zu viele Informationen: Typ A und Typ B, sind die durch Klassen repräsentiert? Gibt es eine gemeinsame Basisklasse (z.B. Person)? Welche Klassen haben die besagten Eigenschaften? Was sind das für Listen, die du da verwendest?

F
Froggie Themenstarter:in
323 Beiträge seit 2007
vor 15 Jahren

Es gibt nur eine Klasse Person und diese hat eine Eigenschaft mit der der Typ (A oder B) der Person festgelegt wird. Ich dachte dafür extra eine Basisklasse und 2 abgeleitete Klassen zu nutzen wäre ineffektiv und übertrieben.
Somit verwende ich auch 2 Listen des selben Typs: List<Person>

Die Lösung von Femaref muss ich mir mal genauer anschauen. So wie es aussieht muss ich da meine Klasse Person erweitern.

Danke nochmal fürs anschauen und drüber nachdenken.

F
240 Beiträge seit 2006
vor 15 Jahren

Es gibt nur eine Klasse Person und diese hat eine Eigenschaft mit der der Typ (A oder B) der Person festgelegt wird. Ich dachte dafür extra eine Basisklasse und 2 abgeleitete Klassen zu nutzen wäre ineffektiv und übertrieben.
Somit verwende ich auch 2 Listen des selben Typs: List<Person>

Die Lösung von Femaref muss ich mir mal genauer anschauen. So wie es aussieht muss ich da meine Klasse Person erweitern.

Danke nochmal fürs anschauen und drüber nachdenken.

Nein, musst du nicht, denn ich habe die Methode mit Absicht so weit gefasst. Wie du das beschreibst, hast du Irgendwie sowas:


public class Person
{
  ....
  public PersonType Type{get;set;}
  ....
}

public enum PersonType
{
  TypeA = 1,
  TypeB = 2
   .....
}

Wenn du dann meine Methode nimmst, sähe die so aus:


public IList<Person> PersonsByType(PersonType filter)
{
  List<Person> output = new List<Person>();
  foreach (Person p in list)
  {
    if(p.Type == filter)
    output.Add(p);
  }
   return output;
}

Somit würdest du nichts verändern müssen. Das gleiche kannste natürlich auch mit einer int-Eigenschaft, oder string-Eigenschaft oder sonstwas machen.

5.299 Beiträge seit 2008
vor 15 Jahren

Ich würde sagen, deine beiden Eigenschaften kannste zu einer zusammenfügen, wenn du sie mit einem Parameter ausstattest, der den Typ angibt (A oder B).
Für Properties bedeutet das, du mußt einen Indexer schreiben.
Wenn deine Eigenschaft readonly ist, kannst du ebensogut eine Methode implementieren. Da isses einfach, einen Parameter hinzuzufügen.

Der frühe Apfel fängt den Wurm.

1.200 Beiträge seit 2007
vor 15 Jahren

Ich würde lieber einen Predicate<T> übergeben und die FindAll Methode von List<T> benutzen. Damit ist man was das Filtern betrifft äusserst flexibel. Bzw. Ich würde gar nicht damit anfangen, so eine Methode zu bauen, sondern gleich die FindAll Methode benutzen.

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

YARRRRRR!

946 Beiträge seit 2008
vor 15 Jahren

Es gibt nur eine Klasse Person und diese hat eine Eigenschaft mit der der Typ (A oder B) der Person festgelegt wird. Ich dachte dafür extra eine Basisklasse und 2 abgeleitete Klassen zu nutzen wäre ineffektiv und übertrieben.

Wenn das wirklich die einzige Gemeinsamkeit der Klasse Person wäre, solltest du das besser über eine Schnittstelle lösen.

Ich glaube aber, ohne genauere Angaben zu kennen, dass da noch mehr Gemeinsamkeiten bestehen. Dann solltest du wirklich eine (ev. abstrakte) Basisklasse benutzen. Das wäre dann soggar effektiver wie deine ursprüngliche Lösung.

1.200 Beiträge seit 2007
vor 15 Jahren

Wenn es sich wirklich um eine Eigenschaft handelt, die alle Personen haben, die aber unterschiedliche Ausprägungen haben kann, sollte man hier vielleicht wirklich mit einer abstrakten Basisklasse oder einem Interface arbeiten. Und zwar für den Typ der Eigenschaft, schließlich handelt es sich wohl um eine "Each person has a" relationship.

Wenn die Eigenschaft einfach nur durch einen String oder ein Enum-Wert repräsentiert werden kann, ist FemaRef's Lösungsvorschlag völlig ausreichend.

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

YARRRRRR!

F
240 Beiträge seit 2006
vor 15 Jahren

*snip*

Hast Recht, sollte ich mich mal mehr mit beschäftigen...