在基类集合上调用派生方法

时间:2014-02-13 06:58:55

标签: c# casting polymorphism covariance

我有一个名为A的抽象类,以及其他实现A的类(B,C,D,E,...)。 我的派生类持有不同类型的值。 我还有一个A对象列表。

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

...其中.val不为基类ofc所知。

我怎样才能获得这种动态行为?我不想在long switch / if-statements中使用getType。

4 个答案:

答案 0 :(得分:3)

如果你只想在每个子类中得到val i重写的字符串表示覆盖ToString

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

如果你想要一个子类中的数据,你需要在基类中将它们表示为它们共有的一些类型(如对象)。你可以这样做

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

答案 1 :(得分:2)

试试这个:

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

答案 2 :(得分:1)

如果val不是基类的成员,则无法在该类型的引用上访问它。这三个派生类可能都有一个名为val的成员,但它不是同一个成员,所以不能像它一样对待它。你可以做的是声明一个泛型类并创建泛型类型的val属性,但是你不能创建该类型的List。基本上,你想做的事情是不可能的。它不是基于继承,而是基于泛型。听起来很方便,但这不合逻辑。

答案 3 :(得分: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));
      }
    }
}