12 votes

Accéder à une propriété d'une classe dérivée à partir de la classe de base en C#

En C#, quelle est la meilleure façon d'accéder à une propriété de la classe dérivée lorsque la liste générique ne contient que la classe de base.

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 Points 98268

Vous pouvez certainement vous baisser, comme ça :

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
    }
}

... Cependant, vous devriez revoir ce que vous essayez d'accomplir. Si vous avez du code commun qui a besoin d'accéder à des propriétés de la classe A et de la classe B, alors il est peut-être préférable d'envelopper l'accès à ces propriétés dans une propriété ou une méthode virtuelle partagée dans la classe ancêtre.

Quelque chose comme :

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
    }
}

5voto

Daniel Earwicker Points 63298

Suite à la réponse de TimJ, vous pouvez écrire une méthode d'extension qui fonctionnera pour tous les types :

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

Ou si vous avez Linq, cette fonction est dans l'espace de noms System.Linq.

2voto

tvanfosson Points 268301
   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 Points 12024

Si vous faites cela souvent, une autre option serait de créer une méthode d'extension sur la liste pour vous rendre l'énumération correctement typée.

  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;
        }
      }
    }
  }

Vous pourriez alors l'utiliser comme....

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 Points 31715

L'ensemble de la prémisse n'a pas de sens - que serait la propriété B pour l'instance a ?

Vous pouvez le faire si vous effectuez une vérification manuelle du type au moment de l'exécution (inst est Foo), puis si vous effectuez un cast vers le type avec la propriété que vous voulez.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X