Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Objekte identifizieren
sra
myCSharp.de - Member



Dabei seit:
Beiträge: 230
Herkunft: Luzern

Themenstarter:

Objekte identifizieren

beantworten | zitieren | melden

Hallo

Ich bin gerade dabei ein kleines Spiel zu programmieren. Nun habe ich einen Timer gemacht, der bei jedem Tick für alle Objekte, die sich bewegen können (IMoveable) in einer ArrayList (Objects) die Methode move() aufzurufen, und danach die refresh() Methode des Fensters (ist bloss ein kleines Projekt und ich arbeite mit GDI+).

Mein Problem ist nun das Identifizieren von Objekten. Ich will eigentlich alle Objekte durchlaufen,welche das Interface IMoveable implementieren. Dazu habe ich folgenden Code:

foreach(IMoveable Object in this.m_Level.Objects)
			{
				Object.move();
			}
Aber irgendwie kommt er nie in zu dem Object.move(), da er gar nie in die Schleife fällt.

Dann hab ich mit der Klasse direkt (Turkey) und einer for Schleife probiert versucht:

for(int i = 0; i < this.m_Level.Objects.Count; i++)
			{
				if(this.m_Level.Objects[i].GetType().ToString() == "demGrenyBattle.Game.Objects.Turkey")
				{
					((Turkey)this.m_Level.Objects[i]).move();
				}

				this.m_Window.Refresh();
			}
Auch das funktioniert nicht, weil er kein einziges mal in die if Anweisung springt. Gebe ich aber über eine MessageBox in der for Schleife den Typen des jeweiligen Objektes aus, dann gibt er mir durchaus auch "demGrenyBattle.Game.Objects.Turkey" aus.

Hat jemand eine Idee? Bin wirklich seit ner halben Stunde am probieren.
Wenn Zeit in Geschichte übergeht und keine Blüten trägt werden Zukunftsbilder blass //Clueso
private Nachricht | Beiträge des Benutzers
talla
myCSharp.de - Experte

Avatar #avatar-3214.jpg


Dabei seit:
Beiträge: 7290
Herkunft: Esslingen

beantworten | zitieren | melden

Den Typennamen als String zu vergleichen ist murks. Du kannst die Typen direkt vergleichen.

Ansich kann bei deiner foreach Schleife nicht viel schiefgehen. Implementieren die Klassen wirklich IMovable? Ist die Collection auch nicht leer?

Du meintest er kommt erst gar nicht in die Schleife, meinst du damit es passt kein Objekt auf IMovable oder das er die Schleife nicht erreicht? Dann müsste in dem Code vorher was schiefgehen.
Baka wa shinanakya naoranai.

Mein XING Profil.
private Nachricht | Beiträge des Benutzers
sra
myCSharp.de - Member



Dabei seit:
Beiträge: 230
Herkunft: Luzern

Themenstarter:

beantworten | zitieren | melden

Wie kann ich denn rausfinden, ob ein Objekt von einem bestimmten Typen ist (ohne es mit einem anderen Objekt zu vergleichen)? Habe nur die Stringlösung gefunden

Zum anderen: Die ArrayList ist nicht leer - es sind alle Objekte vorhanden. In die Schleife komme ich nur im ersten Codebeispiel nicht, da dort die Abfrage ja bereits in der Schleife drin ist (foreach). Im zweiten Beispiel mit der for Schleife komme ich rein, und mache ich direkt in der for-Schleife ein MessageBox.show(), der mir den Typen des jeweiligen Objektes ausgibt, dann kommt wie gesagt dieser Typ vom der Turkeyklasse. Durch die if Abfrage schafft es das Objekt trotzdem nicht.

btw. Ist es auch möglich abzufragen in einer if Anweisung, ob ein Objekt ein bestimmtes Interface implementiert?
Wenn Zeit in Geschichte übergeht und keine Blüten trägt werden Zukunftsbilder blass //Clueso
private Nachricht | Beiträge des Benutzers
marsgk
myCSharp.de - Member



Dabei seit:
Beiträge: 1443
Herkunft: Linz, Austria

beantworten | zitieren | melden

is (C# Reference)

Moderationshinweis von herbivore (14.08.2013 - 15:05:20):

Link korrigiert

private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo sra,

ja, das geht mit dem is-Operator. Aber Vorsicht: explizite Typ-Abfragen sind ein Indiz für schlechtes Design.

herbivore
private Nachricht | Beiträge des Benutzers
sra
myCSharp.de - Member



Dabei seit:
Beiträge: 230
Herkunft: Luzern

Themenstarter:

beantworten | zitieren | melden

Danke - ich werds mal probieren. Allerdings denke ich nicht, dass es damit geht, da es ja in der foreach auch nicht geht. Hat jemand eine Idee, warum meine foreach nicht geht? Ihr könnt davon ausgehen, dass Objects gefüllt ist mit mehreren Objekten, wovon mindestens 3 das Interface IMoveable implementieren und vom Typ Turkey sind.

Ich hab echt keine Idee mehr
Wenn Zeit in Geschichte übergeht und keine Blüten trägt werden Zukunftsbilder blass //Clueso
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo sra,

ich denke, dass er erst gar nicht zu dem foreach kommt. Denn käme er dort hin und würden in this.m_Level.Objects Objekte sein, die IMoveable nicht implementieren, würdest du eine Exception bekommen.

foreach(IMoveable Object in this.m_Level.Objects) heißt, dass alle Objekte in this.m_Level.Objects IMoveable implementieren müssen und nicht etwas, dass das foreach nur für die Objekte ausgeführt wird, die IMoveable implementieren.

herbivore
private Nachricht | Beiträge des Benutzers
sra
myCSharp.de - Member



Dabei seit:
Beiträge: 230
Herkunft: Luzern

Themenstarter:

beantworten | zitieren | melden

hm... dann habe ich foreach nicht richtig verstanden?

Dann mach ich es mal ganz banal. Ich habe in einer ArrayList einige Objekte, die das Interface implementieren, und einige die dies nicht tun. Der Unterschied besteht in erster Linie darin, dass IMoveable Objekte eine Methode move() haben, welche ihre Koordinaten manipuliert. Nun hab ich einen Timer, welcher alle x ms bei allen beweglichen Objekten diese Methode aufrufen soll, damit diese ihre neue Position berechnen und danach darstellen.

Komischerweise geht es mit dem is Operator in der for schleife. Allerdings bin ich auch der Meinung, dass dies nicht wirklich eine schöne Lösung ist.
Wenn Zeit in Geschichte übergeht und keine Blüten trägt werden Zukunftsbilder blass //Clueso
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo sra,

du könntest dir einen Enumerator schreiben, der nur die Objekte, die IMovable implementieren, aufzählt. Ein Beispiel für einen (etwas anderen) Enumerator findest du in foreach iteration gleichzeitig über mehrere arrays . Ist aber für einen Anfänger bestimmt eine Herausforderung.

herbivore
private Nachricht | Beiträge des Benutzers
sra
myCSharp.de - Member



Dabei seit:
Beiträge: 230
Herkunft: Luzern

Themenstarter:

beantworten | zitieren | melden

Is schon traurig, was man als "Programmierlehrling" bis ins 4te Lehrjahr gelehrt bekommt

Ich werd mich mal an deinen Code wagen, obwohl er für mich wirklich eine Nummer zu gross aussieht (nur schon die Rekursion). Aber im Moment quält mich noch eine andere, mit Sicherheit recht einfache Frage.

Im onPaint des frmMain hab ich den Code zum Darstellen meiner Objekte (dieses mal alle und nicht nur die mit dem Interface :D). Mein Problem ist, dass ich von einem anderen objekt aus dieses onPaint Ereignis auslösen muss. Ich dachte das geht ganz einfach, wenn ich dem Objekt eine Referenz auf die frmMain mitgebe, und dann vom Objekt aus .Refresh() auslöse. Leider ist dem nicht so (kein Kompilierfehler, keine Exception).

Wie kann ich das bewerkstelligen?
Wenn Zeit in Geschichte übergeht und keine Blüten trägt werden Zukunftsbilder blass //Clueso
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo sra,

warum musst du das von einem anderen Objekt aus machen? Ich denke, dass wäre nicht notwendig. Im Gegenteil: Ein Objekt sollte in sich abgeschlossen sein. Versuche das Programm so umzustellen, dass frmMain sich selbst Refreshed.

herbivore
private Nachricht | Beiträge des Benutzers
sra
myCSharp.de - Member



Dabei seit:
Beiträge: 230
Herkunft: Luzern

Themenstarter:

beantworten | zitieren | melden

Das muss so sein, weil ich eine Klasse habe, die den ganzen Gameloop managed. Das heisst in ihr ist der Timer, der die Objekte in seinem Event bewegt, in ihr wird der Level instantiert (und in diesem wiederum die Levelobjects...).

Ich denke es ist nur sauber getrennt, wenn ich den ganzen Code nicht im Code des Fensters habe. Oder was meint ihr?
Wenn Zeit in Geschichte übergeht und keine Blüten trägt werden Zukunftsbilder blass //Clueso
private Nachricht | Beiträge des Benutzers
UschkinRedSunshine
myCSharp.de - Member

Avatar #avatar-1829.png


Dabei seit:
Beiträge: 68

beantworten | zitieren | melden

Zitat
Original von sra
Is schon traurig, was man als "Programmierlehrling" bis ins 4te Lehrjahr gelehrt bekommt

Traurig wenn man sich in seiner Bildung auf andere verlaesst und nicht aktiv selbst lernt...

Sinnvoller Ansatz waere auch einfach nur eine "DoSomething" Methode einzufuehren, so durchlaeufst du alle deine Objekte, startest DoSomething, und alle Objekte "bewegen" sich selbst
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo sra,
Zitat
Ich denke es ist nur sauber getrennt, wenn ich den ganzen Code nicht im Code des Fensters habe. Oder was meint ihr?
das, was du da abgetrennt hast, ist der Controler im MVC-Pattern. Die Überlegung ist grundsätzlich sinnvoll. Da der Controler aber in der Regel ohnehin von der Anwendungsart abhängt (Konsole, WindowsForms, Web, ...), würde ich ihn nicht vom (ebenfalls anwendungsartabhängigen) View (also hier dem Form) trennen.

Wenn du es aber doch trennst, sollte der Controler das View kennen (bzw. sogar erzeugen) und kann dann auch problemlos Refresh aufrufen.

herbivore

PS:
Zitat
Traurig wenn man sich in seiner Bildung auf andere verlaesst und nicht aktiv selbst lernt...
Also ich habe gerade in diesem Thread den Eindruck, dass sra sich um das aktiv Selbstlernen bemüht.
private Nachricht | Beiträge des Benutzers
UschkinRedSunshine
myCSharp.de - Member

Avatar #avatar-1829.png


Dabei seit:
Beiträge: 68

beantworten | zitieren | melden

Offtopic:
Zitat
Original von herbivore
Also ich habe gerade in diesem Thread den Eindruck, dass sra sich um das aktiv Selbstlernen bemüht.

Mag sein, wobei die Aussage sich anhoerte wie "Ich verlange das mir alles beigebracht wird, ich aber nichts selbst erarbeiten will"
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo UschkinRedSunshine,

für mich nicht. Dazu kenne ich einfach genug gute Leute, die aktiv selber lernen, und trotzdem bzw. gerade deshalb bedauern, dass die Qualität der (berufs-)schulischen Ausbildung schlecht ist.

herbivore
private Nachricht | Beiträge des Benutzers
sra
myCSharp.de - Member



Dabei seit:
Beiträge: 230
Herkunft: Luzern

Themenstarter:

beantworten | zitieren | melden

Ich werd mir das mal überlegen Herbivore - danke... meld mich wohl morgen mit dem nächsten Problem

Zu dem lernen-Ding kann ich sagen, dass ich leider im Geschäft bisher nur mit vb und asp zu tun hatte, und dass ich in der Schule speziell im objektorientierten Programmieren sehr gute Noten habe. Dazu kommt, dass wir noch ein Semester haben bis die Lehre fertig ist (3 Lektionen programmieren die Woche), und wir in ca. 2 Wochen mal mit Designpatterns anfangen werden. Von da her finde ich das schon schlecht.
Wenn Zeit in Geschichte übergeht und keine Blüten trägt werden Zukunftsbilder blass //Clueso
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo sra,

hier kommt die Klasse MovableEnumerator, mit der du genau das tun kannst, was du willst.

EDIT: Weiter unten gibt es eine Implementierung, bei der der gewünschte Elementtyp als Typparameter übergeben werden kann.


foreach (IMovable mov in new MovableEnumerator (al)) {
   mov.Move ();
}


using System;
using System.Collections;

public class MovableEnumerator : IEnumerator, IEnumerable
{
   private IEnumerator    _ienum;

   public MovableEnumerator (ICollection icoll)
   {
      _ienum = icoll.GetEnumerator ();
   }

   public Object Current
   {
      get { return _ienum.Current; }
   }

   public bool MoveNext ()
   {
      while (_ienum.MoveNext ()) {
         if (_ienum.Current is IMovable) {
            return true;
         }
      }
      return false;
   }

   public void Reset ()
   {
      _ienum.Reset ();
   }

   public IEnumerator GetEnumerator ()
   {
      return this;
   }
}

interface IMovable
{
   void Move ();
}

public class Movable : IMovable
{
   public void Move ()
   {
   }
}

public class NonMovable
{
}

abstract class App
{
   public static void Main (string [] astrArg)
   {
      ArrayList al = new ArrayList ();
      al.Add (new Movable ());
      al.Add (new NonMovable ());
      al.Add (new Movable ());
      al.Add (new NonMovable ());
      al.Add (new Movable ());

      foreach (IMovable mov in new MovableEnumerator (al)) {
         Console.WriteLine (mov.GetType ());
      }
   }
}
Im Gegensatz zu foreach iteration gleichzeitig über mehrere arrays habe ich auf zwei geschachtelte Klassen verzichtet und nur eine Enumerator-Klasse geschrieben und diese Klasse mit einem Trick (return this) foreach-geeignet gemacht.

herbivore
private Nachricht | Beiträge des Benutzers
sra
myCSharp.de - Member



Dabei seit:
Beiträge: 230
Herkunft: Luzern

Themenstarter:

beantworten | zitieren | melden

yeah - Vielen Dank
werds mir gleich anschauen!
Wenn Zeit in Geschichte übergeht und keine Blüten trägt werden Zukunftsbilder blass //Clueso
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo zusammen,

eine überarbeitete Version des MovableEnumerator findet ihr als Iter.Filter [EDIT]und später auch als Iter.Type[/EDIT] in Hilfreiche Iteratoren / Improving Foreach.

herbivore
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo zusammen,

der MovableEnumerator funktionierte ja nur für IMovable. Hier kommt ein Iterator für beliebige Typen. Er listet nur die Elemente der Aufzählung auf, die vom angegebenen Typ sind. Für IMovable sieht der Aufruf so aus:


foreach (IMovable mov in new IterType<IMovable> (al)) {
   mov.Move ();
}


public class IterType<T> : IEnumerator<T>, IEnumerable<T> where T : class
{
   //-----------------------------------------------------------------------
   protected IEnumerator  _enumerator;

   //=======================================================================
   public IterType (IEnumerable enumerable)
   {
      _enumerator = enumerable.GetEnumerator ();
      //Reset ();
   }

   //=======================================================================
   public void Reset ()
   {
      _enumerator.Reset ();
   }

   //=======================================================================
   public bool MoveNext ()
   {
      while (_enumerator.MoveNext ()) {
         if (_enumerator.Current is T) {
            return true;
         }
      }
      return false;
   }

   //=======================================================================
   public T Current
   {
      get { return (T)_enumerator.Current; }
   }

   //=======================================================================
   Object IEnumerator.Current
   {
      get { return _enumerator.Current; }
   }

   //=======================================================================
   public void Dispose ()
   {
      // Nichts zu tun
   }

   //=======================================================================
   public IEnumerator<T> GetEnumerator ()
   {
      return this;
   }

   //=======================================================================
   IEnumerator IEnumerable.GetEnumerator ()
   {
      return this;
   }
}
herbivore
private Nachricht | Beiträge des Benutzers