【问题标题】:Pattern to avoid the need for Downcasting/Reflection避免向下转换/反射需要的模式
【发布时间】:2019-04-08 15:28:21
【问题描述】:

假设我有两个基类的实现:

public class Base { 
    public string Stringify() { return "I am a member of base class"; }
}

public class A : Base {
    public void DoAThing() {...};
}

public class B : Base {
    public void DoBThing(int anInteger) {...};
}

假设我想将Base 的许多实例放在一个列表中,这样我就可以遍历它们并在每个实例上调用Stringify(),并利用它们的共享功能。

static void Main(string[] args)
{
    A thing1 = new A();
    B thing2 = new B();
    B thing3 = new B();     
    List<Base> list = new List<Base> {thing1, thing2, thing3};
    foreach(Base base in list) { Console.WriteLine(base.Stringify()); }           
}

现在假设有很多很多Base 对象,这样维护每个thing 对每个对象的引用是不现实的。是否有任何方法,仅通过列表,可以重新获得抽象丢失的 DoAThing()DoBThing() 功能,而无需使用显式向下转换和反射?

感觉这将是一个足够普遍的事件,所以我想知道是否存在我在这里遗漏的设计缺陷或已建立的模式,这对这种情况会有所帮助。

【问题讨论】:

  • 目前,DoAThingDoBThing 有不同的签名,所以不太清楚你的意思,但总的来说这听起来像是一份工作对于abstract 方法、virtual 方法或interface。你没有展示你打算如何使用DoAThing / DoBThing - 你能澄清一下吗?
  • 就是这样的想法,我打算使用的两种方法的签名不同,所以我不能使用继承来解决问题。本质上我的问题是:如果对象只共享它们的一些功能,我怎样才能将它们存储在集合中而不会失去对特定功能的访问权限?
  • 您可以使用访问者模式,尽管这可能非常冗长。
  • 您能否提供一个示例,说明如何使用向下转换之类的方法来做到这一点?这里可以采用几种方法,但如果没有更具体的示例说明您希望如何使用 DoXThing 方法,很难推荐其中一种。

标签: c# reflection abstraction downcast


【解决方案1】:

如果您进行调试,您会注意到列表中的每个对象都包含其类。

这边:

class Program
{
    static void Main(string[] args)
    {
        A thing1 = new A();
        B thing2 = new B();
        B thing3 = new B();
        List<Base> list = new List<Base> { thing1, thing2, thing3 };
        foreach (Base bas in list) {
            Console.WriteLine(bas.Stringify());

            if(bas is A)
            {
                ((A)bas).DoAThing();
            }
            else if (bas is B)
            {
                ((B)bas).DoBThing(1);
            }
            else
            {
                //IDK
            }
        }
    }

}

public abstract class Base
{
    public string Stringify() { return "I am a member of base class"; }
}

public class A : Base
{
    public void DoAThing()
    {

    }
}

public class B : Base
{
    public void DoBThing(int anInteger)
    {

    }
}

【讨论】:

  • 这不是低调吗?
  • 向下转型是一种从基类引用创建子类引用的操作。
  • 你在用((A)bas)做什么
  • @Lee 是的,你是对的。我坚持通过接口而不是类来做这件事会对 OP 产生影响
猜你喜欢
  • 2014-08-12
  • 2017-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多