none
Typ einer Klasse übergeben RRS feed

  • Frage

  • Hallo zusammen,

     

    ich habe folgendes Problem: Ich habe mehrere Klassen (hier TestA und TestB) die ich von der gleichen Basisklasse abgeleitet habe (Test).

    Eine Klasse 'Klasse' enthält ein Array, in dem sich mehrere Elemente der Basisklasse Test befinden, entweder TestA oder TestB. Nun möchte ich mit Hilfe der Methode sucheElement entweder die erste TestA - Instanz des Arrays oder die erste TestB-Instanz des Arrays zurückgeben lassen.

    Ich habe mir gedacht, dass ich dazu evtl. eine neue Instanz der gesuchten Klasse als Parameter übergebe und dann die Typen dieser neuen Instanz mit den Typen im Array vergleiche, aber irgendwie weiß ich nicht weiter...

    Ich hoffe, dass ihr mein Problem versteht, ansonsten bitte nachfragen!

    Im Voraus schon vielen Dank für Lösungsvorschläge.

    MfG stes

     

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Problem
    {
      class Test {/* ... */}
      class TestA : Test {/* ... */}
      class TestB : Test {/* ... */}
    
    
      class Program
      {
        static void Main()
        {
          Klasse myKlasse = new Klasse();
          // Übergabe der neuen TestA-Instanz
          TestA TestAInstanz = (TestA)myKlasse.sucheElement(new TestA());
        }
      }
    
      class Klasse
      {
        public Klasse()
        {
          meineObjekte = new Test[2];
          meineObjekte[0] = new TestA();
          meineObjekte[1] = new TestB();
        }
    
        public Test[] meineObjekte;
        public Test sucheElement(Test typ)
        {
          foreach (Test temp in meineObjekte)
          {
            // Wenn temp den gleichen Typ hat wie der Parameter typ, soll
            // er zurückgegeben werden.
            if (/* Typ von temp == Typ von typ */)
              return temp;
          }
        }
      }
    }
    

    Dienstag, 19. Oktober 2010 13:16

Antworten

  • Hallo,

    Den Vergleich, ob eine Instanz einem bestimmten Type entspricht kannst Du via Object.GetType durchführen.
    Wenn Du eine Klasse von einem bestimmten Type suchst, brauchst Du dafür keine Instanz zu erstellen.
    Effizienter ist es dafür typeof zu verwenden, siehe zweite Variante im Beispiel.
    Oder auch eine generische Methode zu verwenden, wie im dritten Beispiel gezeigt.

    internal class Klasse
    {
      private Test[] meineObjekte = new Test[] { new TestB(), new TestA() };
    
      /// <summary>Suche anhand einer Instanz.</summary>
      public Test SucheElement(Test typ)
      {
        var typType = typ.GetType(); // Ermitteln des Typs
        foreach (Test temp in meineObjekte)
        {
          if (typType == temp.GetType())
            return temp;
        }
        return null;
      }
    
      /// <summary>Suchen mithilfe von System.Type.</summary>
      public Test SucheElement(Type type)
      {
        // LINQ anstatt foreach
        return meineObjekte.FirstOrDefault(e => type == e.GetType());
      }
    
      /// <summary>Suchen mithilfe generischer Typangabe.</summary>
      public TClass SucheElement<TClass>() where TClass : Test
      {
        // Generische Variante 
        return (TClass)meineObjekte.FirstOrDefault(e => typeof(TClass) == e.GetType());
      }
    
      internal static void SucheElement()
      {
        Klasse myKlasse = new Klasse();
        // Übergabe der neuen TestA-Instanz
        TestA instanz1 = (TestA)myKlasse.SucheElement(new TestA());
        TestA instanz2 = (TestA)myKlasse.SucheElement(typeof(TestA));
    
        // Kein Cast mehr erforderlich
        TestA instanz3 = myKlasse.SucheElement<TestA>();
    
        // Alle drei Methdoen sollten identische Ergebnisse liefern
        System.Diagnostics.Debug.Assert(instanz1 != null
          && Object.ReferenceEquals(instanz1, instanz2)
          && object.ReferenceEquals(instanz1, instanz3),
          "Kein gleiches Ergebnis");
      }
    }

    Im zweiten und dritten Beispiel habe ich die Schleife durch einen Lambda-Ausdruck und Linq "wegrationalisiert".

    Für weitere Experimente:
    Willst Du ermitteln, ob ein Type von einem anderen abgeleitet ist, wie man es statisch mittels dem Is-Operator macht,
    ginge das über Type.IsAssignableFrom . Was man z. B. braucht, wenn eine Klasse TestC von TestA abgeleitet wird.

    Gruß Elmar

    • Bearbeitet Elmar Boye Dienstag, 19. Oktober 2010 16:37 Format
    • Als Antwort markiert stes Dienstag, 19. Oktober 2010 17:35
    Dienstag, 19. Oktober 2010 16:34

Alle Antworten

  • Hallo stes,

    leider kann ich nicht genau nachvollziehen, wo dein Problem liegt. Beschreib es etwas genauer. Wenn das dein Orginalcode ist:

    Bei deiner  IF Schleife fehlen die Klammern.

    nicht

     if (/* Typ von temp == Typ von typ */)
             return temp;

    sondern

     if (/* Typ von temp == Typ von typ */)

    {

    return temp;

    }

    Schöne Gtüße

    Oliver

    Dienstag, 19. Oktober 2010 13:36
  • Hallo,

    Den Vergleich, ob eine Instanz einem bestimmten Type entspricht kannst Du via Object.GetType durchführen.
    Wenn Du eine Klasse von einem bestimmten Type suchst, brauchst Du dafür keine Instanz zu erstellen.
    Effizienter ist es dafür typeof zu verwenden, siehe zweite Variante im Beispiel.
    Oder auch eine generische Methode zu verwenden, wie im dritten Beispiel gezeigt.

    internal class Klasse
    {
      private Test[] meineObjekte = new Test[] { new TestB(), new TestA() };
    
      /// <summary>Suche anhand einer Instanz.</summary>
      public Test SucheElement(Test typ)
      {
        var typType = typ.GetType(); // Ermitteln des Typs
        foreach (Test temp in meineObjekte)
        {
          if (typType == temp.GetType())
            return temp;
        }
        return null;
      }
    
      /// <summary>Suchen mithilfe von System.Type.</summary>
      public Test SucheElement(Type type)
      {
        // LINQ anstatt foreach
        return meineObjekte.FirstOrDefault(e => type == e.GetType());
      }
    
      /// <summary>Suchen mithilfe generischer Typangabe.</summary>
      public TClass SucheElement<TClass>() where TClass : Test
      {
        // Generische Variante 
        return (TClass)meineObjekte.FirstOrDefault(e => typeof(TClass) == e.GetType());
      }
    
      internal static void SucheElement()
      {
        Klasse myKlasse = new Klasse();
        // Übergabe der neuen TestA-Instanz
        TestA instanz1 = (TestA)myKlasse.SucheElement(new TestA());
        TestA instanz2 = (TestA)myKlasse.SucheElement(typeof(TestA));
    
        // Kein Cast mehr erforderlich
        TestA instanz3 = myKlasse.SucheElement<TestA>();
    
        // Alle drei Methdoen sollten identische Ergebnisse liefern
        System.Diagnostics.Debug.Assert(instanz1 != null
          && Object.ReferenceEquals(instanz1, instanz2)
          && object.ReferenceEquals(instanz1, instanz3),
          "Kein gleiches Ergebnis");
      }
    }

    Im zweiten und dritten Beispiel habe ich die Schleife durch einen Lambda-Ausdruck und Linq "wegrationalisiert".

    Für weitere Experimente:
    Willst Du ermitteln, ob ein Type von einem anderen abgeleitet ist, wie man es statisch mittels dem Is-Operator macht,
    ginge das über Type.IsAssignableFrom . Was man z. B. braucht, wenn eine Klasse TestC von TestA abgeleitet wird.

    Gruß Elmar

    • Bearbeitet Elmar Boye Dienstag, 19. Oktober 2010 16:37 Format
    • Als Antwort markiert stes Dienstag, 19. Oktober 2010 17:35
    Dienstag, 19. Oktober 2010 16:34
  • Vielen Dank, funktioniert wunderbar! Habe mir gedacht das das irgendwie auch ohne die 'Hilfsinstanz' gehen muss, aber mit Linq habe ich noch nicht wirklich gearbeitet :-) Denke, dass ich da was nachholen muss.

     

    lg stes


    visit my website: www.parallelportprogramming.webs.com
    Dienstag, 19. Oktober 2010 17:34
  • Nein wenn man nur einen Befehl hinter if ausführen will, kann man sich in C# die Klammern getrost sparen ;)
    visit my website: www.parallelportprogramming.webs.com
    Dienstag, 19. Oktober 2010 17:36
  • Hi,

    die Klammer kann man sich sparen, solltest du aber nicht. Behandle einfach sämtliche if-Statements gleich, selbst wenn innerhalb deines if-Statements nur eine Anweisung steht. Wenn du dir das angewöhnst, sieht dein Code immer gleich aus und ist auch lesbarer. Nur so als kleiner Tipp von mir ;o)

    Viele Grüße

    Holger M. Rößler

    Montag, 25. Oktober 2010 13:58