Laden...

Mehrere Indexer in einer Klasse

Erstellt von toxic vor 13 Jahren Letzter Beitrag vor 13 Jahren 1.776 Views
Thema geschlossen
T
toxic Themenstarter:in
64 Beiträge seit 2010
vor 13 Jahren
Mehrere Indexer in einer Klasse

Hallo, ich brauche mal eure Hilfe...

Es geht um folgendes.
Wenn ich mir eine Klasse bastel die mit Indexer aufgebaut ist sieht das ja ungefähr so aus.


public class Fußballmannschaft {
  private Spieler[] team = new Spieler[25];
  // Indexer
  public Spieler this[int index] {
    get { return team[index]; }
    set {
      // prüfen, ob der Index schon belegt ist
      if (team[index] == null)
        team[index] = value;
      else
        // nächsten freien Index suchen
        for (int i = 0; i < 25; i++) {
          if (team[i] == null) {
            team[i] = value;
            return;
          }
        } 
    }
  }
}


Was passiert jetzt aber wenn ich noch einen Indexer in der Selben Klasse bräuchte?
z.b. in diesem Beispiel, ich möchte noch einen Indexer "Trainer"


public class Fußballmannschaft {
  private Spieler[] team = new Spieler[25];
  private Trainer[] trainer = new Trainer[10];
  // Indexer
  public Spieler this[int index] {... } 
  public Trainer this[int index] {... }   <---
    }
  }
}


Wie oder woher weiss ich dann auf welches Array ich zugreife?

Ich glaub ich seh den Wald vor lauter Bäumen nicht.

Danke!

Gruß Matthias

916 Beiträge seit 2008
vor 13 Jahren

Hallo toxic,

Wenn ich mir eine Klasse bastel die mit Indexer aufgebaut ist sieht das ja ungefähr so aus.

richtig. Nur kannst du nicht 2 Siganturen mit der selben Schnittstelle die sich nur im Returntyp unterscheiden in ein und die selbe Klasse packen. Das funktioniert so nicht. Du müsstest das Trainer Array einfach via Property raus reichen. Im übrigen solltest du auf List<T> umsteigen, die sind erheblich besser zu bedienen.

Mich als Programmierer würde es sowieso verwirren wenn ich auf ein Indexer einer Fussballmannschaft die Trainer zurück bekommen würde...

Again what learned...

T
toxic Themenstarter:in
64 Beiträge seit 2010
vor 13 Jahren

Danke, für die super schnell Hilfe!
Ich werds wohl über eine Property lösen...

Die Trainer waren ja nur fiktiv =)

916 Beiträge seit 2008
vor 13 Jahren

Was du alternativ noch machen kannst ist den key des Indexer's zu ändern. Daher folgendes würde kompilieren:


public class Fußballmannschaft {
  private Spieler[] team = new Spieler[25];
  private Trainer[] trainer = new Trainer[10];
  // Indexer
  public Spieler this[int index] {... }
  public Trainer this[string key] {... }   <---
    }
  }
 

Again what learned...

1.552 Beiträge seit 2010
vor 13 Jahren

Was du alternativ noch machen kannst ist den key des Indexer's zu ändern. Daher folgendes würde kompilieren:

Es würd zwar kompilieren, aber m.e. ist es konfus, denn ich würde von 2 Indexern erwarten dass sie dasselbe zurückgeben, nur der Aufruf kann auf die eine oder Andere Weiße einfacher sein.

set {  
    // prüfen, ob der Index schon belegt ist  
    if (team[index] == null)  
        team[index] = value;  
    else  
        // nächsten freien Index suchen  
        for (int i = 0; i < 25; i++) {  
            if (team[i] == null) {  
                team[i] = value;  
                    return;  
            }  
        }  
}  

M.e. ist dies nicht ganz korrekt dass du den nächsten freien Index dem Element gibst. Ich stütze mich auf folgendes Beispiel:

Fußballmannschaft fm = new Fußballmannschaft();
fm[1] = new Spieler(); //zugewiesen an index position 1
fm[1] = new Spieler(); //zugewiesen an index position 2
fm[1] = null;

woher soll ich nun wissen wie ich auf den 2.Spieler im Array zugreifen kann.

Note an deinen Programmierungsstyle: else for(....):
Natürlich kann man eine Einzeilige Anweißung nach dem else ohne geschweifte Klammern schreiben, jedoch ist deine Anweißung optisch nicht eine Zeile, ansonsten schon. Es ist sehr verwirrend wenn so lange Blöcke nicht in Klammern geschrieben werden.

Gruß
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

916 Beiträge seit 2008
vor 13 Jahren
  
fm[1] = new Spieler(); //zugewiesen an index position 1  
fm[1] = new Spieler(); //zugewiesen an index position 2  
  

Das Konstrukt ist doch schon insich Sinnfrei...Und der Kommentar hinter der 2ten LineOfCode erst recht.

Again what learned...

1.552 Beiträge seit 2010
vor 13 Jahren

Und der Kommentar hinter der 2ten LineOfCode erst recht.

Warum? Position 1 soll a[0] sein Position 2 a[1]

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

1.815 Beiträge seit 2005
vor 13 Jahren

Hallo!

@rollerfreak2:
Ich denke mal, xxMUROxx wollte damit genau darauf hinweisen, dass der Indexer in seiner Logik nicht dem entspricht, was man bei der Verwendung erwarten würde (also, dass mit einem angegebenen Index auch exakt die Position angesprochen wird. Im ersten Post sieht man jedoch, dass beim Setter die nächste freie Position gesucht wird, beim Getter hingegen die übergebene Position, Getter und Setter arbeiten somit nicht konsistent.

Nobody is perfect. I'm sad, i'm not nobody 🙁

916 Beiträge seit 2008
vor 13 Jahren

Das habe ich schon verstanden, nichst desto trotz macht der Code nicht mal Sinn wenn Setter und Getter "gleich" arbeiten. Weil er beides mal index Position 1 anspricht, und nicht wie im Kommentar dahinter 1 und 2!

Aber nun weiß ich worauf er hinaus wollte 😄

Again what learned...

1.378 Beiträge seit 2006
vor 13 Jahren

Abgesehen davon, dass der Code wie vorher schon erwähnt fragwürdig ist hier eine Möglichkeit für mehrere (benannte) Indexer:

Einfach im Code an der gewünschten Stelle das Snippet 'iterindex' einfügen und Tab drücken sollte dann folgenden Code produzieren:

    public MyViewIterator MyView
    {
        get
        {
            return new MyViewIterator(this);
        }
    }

    public class MyViewIterator
    {
        readonly TestClass outer;

        internal MyViewIterator(TestClass outer)
        {
            this.outer = outer;
        }

        // TODO: provide an appropriate implementation here
        public int Length { get { return 1; } }

        public ElementType this[int index]
        {
            get
            {
                //
                // TODO: implement indexer here
                //
                // you have full access to TestClass privates
                //
                throw new NotImplementedException();
                return default(ElementType);
            }
        }

        public System.Collections.Generic.IEnumerator<ElementType> GetEnumerator()
        {
            for (int i = 0; i < this.Length; i++)
            {
                yield return this[i];
            }
        }
    }

und da drinnen kannst du dich dann mit deiner Setterlogik austoben soviel du willst. Ich würd aber trotzdem die Anforderungen überdenken und schauen ob der Indexer hier die beste Lösung ist.

Lg XXX

1.552 Beiträge seit 2010
vor 13 Jahren

Weil er beides mal index Position 1 anspricht, und nicht wie im Kommentar dahinter 1 und 2!

Ja es kann sein dass ich mich vielleicht etwas ungünstig ausgesprochen habe, aber ich spreche im code 2x die Position 1 an, aber im Kommentar steht doch

zugewiesen an index position 2

Ich verstehe unter zuweisen und ansprechen etwas anderes. Ich spreche zwar Position 1 an, zugewiesen wird es an Position 2.

Aber nun weiß ich worauf er hinaus wollte 😄

Genau. Es soll so sein wie es tom-essen sagte.

Gruß
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

5.742 Beiträge seit 2007
vor 13 Jahren

Ich würd aber trotzdem die Anforderungen überdenken und schauen ob der Indexer hier die beste Lösung ist.

Ja!
Zwei Properties scheinen mir hier irgendwie geeigneter - es könnte sich ja auch um ReadOnlyCollections handeln handeln, die über Methoden (z.B. AddSpieler) manipuliert werden.

Thema geschlossen