bei typisierten Listen Basisklasse des Typs erstellen



  • Und wie würde ich sowas dann lösen?



  • Ein CopyTo oder ConvertTo Funktion schreiben.



  • Oder generisch arbeiten:

    public void Test<T>(List<T> list) where T : A {
        foreach (A item in list) {
        }
    }
    


  • Oder aus List<B> bList einfach List<A> bList machen! 😉



  • Hallo,

    hier ein kleines Beispiel zur Veranschaulichung:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace DerivedClassInGenericList
    {
        class Program
        {
            static void Main(string[] args)
            {
                Test();
    
                Console.WriteLine("\nHIT ENTER TO EXIT.");
                Console.ReadLine();
            }
    
            public static void Test()
            {
                List<A> lst = new List<A>();
    
                Console.WriteLine("Adding one B-object to the list.");
                lst.Add(new B());
                Console.WriteLine("Adding one A-object to the list.");
                lst.Add(new A());
    
                Console.WriteLine("\nListing items by casting all list items to the base class (A):");
                foreach (A item in lst)
                    Console.WriteLine(item.Name);
    
                try
                {
                    Console.WriteLine("\nListing items by casting all items to the derived class (B):");
                    foreach (B item in lst)
                        Console.WriteLine((item as A).Name);
                }
                catch (InvalidCastException ex)
                {
                    Console.WriteLine("Ooops...\nYou can cast a derived class (B) to a base class (A).\nBut you cannot cast the base class (A) to a class derived from it (B).");
                }
    
                Console.WriteLine("\nListing anyway. Everything is an object:");
                foreach (object item in lst)
                    if (item is A)
                        Console.WriteLine((item as A).Name);
                    else if (item is B)
                        Console.WriteLine((item as B).Name);
            }
        }
    
        public class A
        {
            public virtual string Name { get { return "A"; } }
        }
    
        public class B : A
        {
            public override string Name { get { return "B"; }}
        }
    }
    


  • Dieses Stück Code ist total überflüssig! 💡

    else if (item is B)
        Console.WriteLine((item as B).Name);
    

    Möglich wäre auch gewesen:

    public void test(IEnumerable aList)
    


  • David_pb schrieb:

    Dieses Stück Code ist total überflüssig!

    So ist es. Zumindest so lange man mit der abgeleiteten Klasse nichts spezifisches vor hat...



  • maro158 schrieb:

    David_pb schrieb:

    Dieses Stück Code ist total überflüssig!

    So ist es. Zumindest so lange man mit der abgeleiteten Klasse nichts spezifisches vor hat...

    Selbst in diesem Fall würde der else-Zweig nie erreicht werden. 🙂



  • David_pb schrieb:

    Selbst in diesem Fall würde der else-Zweig nie erreicht werden. 🙂

    Und schon wieder hast Du recht. Also, ich korrigiere:

    if (item is B)
                        Console.WriteLine((item as B).Age);
                    else if (item is A)
                        Console.WriteLine((item as A).Name);
    

    👍

    Nun, das meinte ich.



  • Anmerkung: Man kann übrigens auch auf einen konkreten Typen testen.

    if (item.GetType() == typeof( B ) )
       Console.WriteLine((item as B).Age);
    else if (item.GetType() == typeof( A ) )
       Console.WriteLine((item as A).Name);
    


  • bool b = item.GetType() == typeof( B );
    

    ist daselbe wie

    bool b = item is B;
    


  • simon.gysi schrieb:

    bool b = item.GetType() == typeof( B );
    

    ist daselbe wie

    bool b = item is B;
    

    Durchaus nicht:

    class A
      {
      }
    
      class B : A
      {
      }
    
      class C : B
      {
      }
    
      class Program
      {
        static void Main(string[] args)
        {
          A x = new C();
          Test1( x );
          Test2( x );
    
          Console.ReadKey();
        }
    
        static void Test1( object x )
        {
          if ( x is A )
            Console.WriteLine( "is A" );
    
          if ( x is B )
            Console.WriteLine( "is B" );
    
          if ( x is C )
            Console.WriteLine( "is C" );
        }
    
        static void Test2( object x )
        {
          if ( x.GetType() == typeof( A ) )
            Console.WriteLine( "_is_ A" );
    
          if ( x.GetType() == typeof( B ) )
            Console.WriteLine( "_is_ B" );
    
          if ( x.GetType() == typeof( C ) )
            Console.WriteLine( "_is_ C" );
        }
      }
    


  • 100% acknowledge.



  • David_pb schrieb:

    Durchaus nicht

    Ein Blick hinter die Kulissen:

    // if (item.GetType() == typeof(B))
        IL_0107:  ldloc.s    V_6
        IL_0109:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
        IL_010e:  ldtoken    DerivedClassInGenericList.B
        IL_0113:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        IL_0118:  ceq
    
    // if (item is B)
        IL_0107:  ldloc.s    V_6
        IL_0109:  [b]isinst[/b]     DerivedClassInGenericList.B
        IL_010e:  ldnull
        IL_010f:  cgt.un
    

    Wie man im letzten IL-Codeblock sieht, wird im Fall von if (item is 😎 einfach isinst aufgerufen. Isinst übeprüft ob die auf dem Stack abgelegte Referenz vom Typ DerivedClassInGenericList.B ODER ein von DerivedClassInGenericList.B abgeleiteter Typ ist.



  • Genau so ist das! 🙂



  • Ohje!

    Ich denke die generische Definition ist hier die beste Lösung für mich 🙂 Ich werd das mal probieren.

    Danke euch allen!


Anmelden zum Antworten