13 Stimmen

Zugriff auf eine Eigenschaft einer abgeleiteten Klasse von der Basisklasse in C#

Was ist in C# der beste Weg, um auf eine Eigenschaft der abgeleiteten Klasse zuzugreifen, wenn die generische Liste nur die Basisklasse enthält.

public class ClassA : BaseClass
{
   public object PropertyA { get; set; }
}

public class ClassB: BaseClass
{
    public object PropertyB { get; set; }
}

public class BaseClass
{
}

public void Main
{
    List<BaseClass> MyList = new List<BaseClass>();
    ClassA a = new ClassA();
    ClassB b = new ClassB();

    MyList.Add(a);
    MyList.Add(b);

    for(int i = 0; i < MyList.Count; i++)
    {
        //I would like to access PropertyA abd PropertyB from the derived classes        
    }
}

23voto

Matt Hamilton Punkte 193704

Natürlich können Sie sich auch nach unten wenden, etwa so:

for (int i = 0; i < MyList.Count; i++)
{
    if (MyList[i] is ClassA)
    {
        var a = ((ClassA)MyList[i]).PropertyA;
        // do stuff with a
    }

    if (MyList[i] is ClassB)
    {
        var b = ((ClassB)MyList[i]).PropertyB;
        // do stuff with b
    }
}

... Sie sollten sich jedoch noch einmal ansehen, was Sie erreichen wollen. Wenn Sie einen gemeinsamen Code haben, der auf Eigenschaften von KlasseA und KlasseB zugreifen muss, dann sollten Sie den Zugriff auf diese Eigenschaften besser in eine gemeinsame virtuelle Eigenschaft oder Methode in der Vorgängerklasse verpacken.

Etwa so:

public class BaseClass
{
    public virtual void DoStuff() { }
}

public class ClassA : BaseClass
{
    public object PropertyA { get; set; }

    public override void DoStuff() 
    {
        // do stuff with PropertyA 
    }
}

public class ClassB : BaseClass
{
    public object PropertyB { get; set; }

    public override void DoStuff() 
    {
        // do stuff with PropertyB
    }
}

0 Stimmen

Ich muss etwas übersehen haben, aber warum brauchen Sie DoStuff() en BaseClass wenn Sie es einfach in den abgeleiteten Klassen programmieren? Würden Sie nicht einfach eine Schnittstelle verwenden, um die Einbeziehung von DoStuff() in den abgeleiteten Klassen?

0 Stimmen

@SteveCinq Denn auf diese Weise können Sie die Methode auf dem BaseClass-Objekt aufrufen, ohne den genauen abgeleiteten Typ der Klasse kennen zu müssen.

5voto

Daniel Earwicker Punkte 111630

Im Anschluss an TimJs Antwort können Sie eine Erweiterungsmethode schreiben, die für alle Typen funktioniert:

public static IEnumerable<T> OfType<T>(this IEnumerable list)
{
    foreach (var obj in list)
    {
        if (obj is T)
            yield return (T)obj;
    }
}

Wenn Sie Linq verwenden, befindet sich diese Funktion im Namespace System.Linq.

2voto

tvanfosson Punkte 506878
   BaseClass o = MyList[i];
   if (o is ClassB)
   {
      object k = ((ClassB)o).PropertyB;
   }
   if (o is ClassA))
   {
      object j = ((ClassA)o).PropertyA;
   }

2voto

Tim Jarvis Punkte 17605

Wenn Sie dies häufig tun, wäre eine andere Möglichkeit, eine Erweiterungsmethode für die Liste zu erstellen, die Ihnen die korrekt getippte Aufzählung zurückgibt, z. B.

  public static class MyBaseListExtensions
  {
    public static IEnumerable<ClassA> GetAllAs(this List<MyBaseClass> list)
    {
      foreach (var obj in list)
      {
        if (obj is ClassA)
        {
          yield return (ClassA)obj;
        }
      }
    }

    public static IEnumerable<ClassB> GetAllbs(this List<MyBaseClass> list)
    {
      foreach (var obj in list)
      {
        if (obj is ClassB)
        {
          yield return (ClassB)obj;
        }
      }
    }
  }

Dann könnten Sie es wie.... verwenden.

private void button1_Click(object sender, EventArgs e)
{
  ClassA a1 = new ClassA() { PropertyA = "Tim" };
  ClassA a2 = new ClassA() { PropertyA = "Pip" };
  ClassB b1 = new ClassB() { PropertyB = "Alex" };
  ClassB b2 = new ClassB() { PropertyB = "Rachel" };

  List<MyBaseClass> list = new List<MyBaseClass>();
  list.Add(a1);
  list.Add(a2);
  list.Add(b1);
  list.Add(b2);

  foreach (var a in list.GetAllAs())
  {
    listBox1.Items.Add(a.PropertyA);
  }

  foreach (var b in list.GetAllbs())
  {
    listBox2.Items.Add(b.PropertyB);
  }
}

1voto

Adam Wright Punkte 48270

Die ganze Prämisse macht keinen Sinn - was wäre PropertyB für die a-Instanz?

Dies ist möglich, wenn Sie zur Laufzeit eine manuelle Typüberprüfung durchführen (inst ist Foo) und dann auf den Typ mit der gewünschten Eigenschaft casten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X