2014-02-13 16 views
6

Ich habe eine abstrakte Klasse namens A und andere Klassen (B, C, D, E, ...), die implementiert. Meine abgeleiteten Klassen halten Werte verschiedener Typen. Ich habe auch eine Liste von A-Objekten.Aufruf abgeleiteter Methoden auf einer Basisklassensammlung

abstract class A { } 
    class B : class A 
    { 
     public int val {get;private set;} 
    } 
    class C : class A 
    { 
     public double val {get;private set;} 
    } 
    class D : class A 
    { 
     public string val {get;private set;} 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      List list = new List { new B(), new C(), new D(), new E() }; 
      // ... 

      foreach (A item in list) 
      { 
      Console.WriteLine(String.Format("Value is: {0}", item.val); 
      } 
     } 
    } 

... wobei die .val nicht von der Basisklasse ofc bekannt ist.

Wie kann ich dieses dynamische Verhalten erhalten? Ich möchte getType nicht in langen switch/if-Anweisungen verwenden.

+1

Die Tatsache, dass die Klassen erben von 'A' spielt hier keine Rolle -' A' keinen 'val', so die Unterklassen' val 's sind nicht verwandt. Sie können auch einfach 'object' als Basisklasse verwenden. Ich denke, das klingt so, als ob Sie 'dynamic' verwenden möchten, wenn Sie C# 4.0+ – Blorgbeard

+1

@Blorgbeard One kleine Korrektur verwenden. C# 4.0 sowie .net 4.0 –

Antwort

2

Versuchen Sie folgendes:

using System; 
using System.Collections.Generic; 

abstract class A 
{ 
    public abstract dynamic Val { get; set; } 

} 
class B : A 
{ 
    public override dynamic Val { get; set; } 
} 
class C : A 
{ 
    public override dynamic Val { get; set; } 
} 
class D : A 
{ 
    public override dynamic Val { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var list = new List<A> { new B(), new C(), new D() }; 
     // ... 

     foreach (A item in list) 
     { 
      Console.WriteLine(String.Format("Value is: {0}", item.Val)); 
     } 
    } 
} 
+0

Ich hatte eigentlich "dynamische" in C# vergessen, weil ich nie etwas 'dynamisches' erklärt habe und es immer nur mit' ViewBag' in einer MVC-App benutze. Es wird immer noch nicht ganz das bekommen, was das OP verlangt, weil die überschriebenen Member nicht stark typisiert sind, also muss Code, der sie benutzt, das Ergebnis noch werfen und sie werden nicht einschränken, was ihnen zugewiesen werden kann. Es ist so nah wie du kommst. – jmcilhinney

+0

@jmcilhinney so verwenden Sie das Objekt –

+0

Der Typ wird intern in den abgeleiteten Klassen beim Zuweisen von Werten festgelegt. Das Schöne ist, dass Sie einen beliebigen Werttyp festlegen können, und das "Override" ist möglich, da es in der Basis- und der abgeleiteten Klasse vom selben Typ (dynamisch) ist. Mit den überschriebenen Werten (get) können Sie den toString() mit polymorphem Verhalten aufrufen. – Omicron

1

Wenn val ist kein Mitglied der Basisklasse, dann können Sie es nicht auf einem dieser Typenbezeichnung zuzugreifen. Diese drei abgeleiteten Klassen können alle ein Mitglied mit dem Namen val haben, aber es ist NICHT das gleiche Mitglied, so dass es nicht so behandelt werden kann, wie es ist. Sie könnten eine generische Klasse deklarieren und die Eigenschaft val des generischen Typs festlegen, aber dann könnten Sie keine Liste dieses Typs erstellen. Grundsätzlich ist das, was Sie tun möchten, nicht möglich. Es basiert nicht auf Vererbung und basiert nicht auf Generika. Es klingt bequem, aber es ist nicht logisch.

3

Wenn Sie nur die Stringdarstellung val erhalten möchten i recoment in jeder der Unterklassen überschreiben ToString

public override string ToString() 
{ 
    return val.ToString(); 
} 

entweder Weg, wenn Sie die Daten in einer Unterklasse wollen, müssen Sie es in die vertreten Basisklasse als einen Typ, den alle gemeinsam haben (wie Objekt). und man könnte es tun, wie diese

abstract class A 
{ 
    public abstract object GetValue(); 
} 
class B : class A 
{ 
    public int val {get;private set;} 
    public override object GetValue() 
    { 
     return val; 
    } 
} 
1
abstract class A { public string val { get; set; } } 
class B : A 
{ 
    public int val {get;private set;} 
} 
class C : A 
{ 
    public double val {get;private set;} 
} 
class D : A 
{ 
    public string val {get;private set;} 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<object> list = new List<object> { new B(), new C(), new D() }; 
     // ... 

     foreach (A item in list) 
     { 
     Console.WriteLine(String.Format("Value is: {0}", item.val)); 
     } 
    } 
}