C# 在不同子类的ArrayList中访问正确的函数

C# 在不同子类的ArrayList中访问正确的函数,c#,arraylist,C#,Arraylist,假设我有以下三门课: 父类: public class ParentClass { public void foo() { Debug.Log("Parent called!"); } } 第一儿童班: public class ChildOne : ParentClass { public new void foo() { Debug.Log("Child one called!"); } } public class Chi

假设我有以下三门课:

父类:

public class ParentClass {
    public void foo() {
        Debug.Log("Parent called!");
    }
}
第一儿童班:

public class ChildOne : ParentClass {
    public new void foo() {
        Debug.Log("Child one called!");
    }
}
public class ChildTwo : ParentClass {
    public new void foo() {
        Debug.Log("Child two called!");
    }
}
第二儿童班:

public class ChildOne : ParentClass {
    public new void foo() {
        Debug.Log("Child one called!");
    }
}
public class ChildTwo : ParentClass {
    public new void foo() {
        Debug.Log("Child two called!");
    }
}
在第四个类中,我有一个ArrayList,它包含多个ChildOne和ChildTwo对象。ArrayList不包含任何其他类型的对象

如何访问子对象的foo()函数

public class Example {
    public void someFunction() {
        //...

        ArrayList children = new ArrayList();
        children.add(new ChildOne());
        children.add(new ChildTwo());

        children[0].foo(); //here I want to call the foo() function of the ChildOne object
        children[1].foo(); //here I want to call the foo() function of the ChildTwo object

        //...
    }
}
强制转换到父类不起作用,我不能强制转换到其中一个子类,因为我不知道每个元素的类型

带反射:

var child = children[0];
Type childType = child.GetType();
MethodInfo mi = childType.GetMethod("foo");
mi.Invoke(child, new object[]{});
带着沉思:

var child = children[0];
Type childType = child.GetType();
MethodInfo mi = childType.GetMethod("foo");
mi.Invoke(child, new object[]{});

如果可以,可以使用多态性而不是隐藏父函数的foo函数

为了实现此结果,我们可以将父类转换为foo方法虚拟,以便在子类中重写它:

public class ParentClass {
    public virtual void foo() {
        Debug.Log("Parent called!");
    }
}
然后在children类中,我们将new关键字替换为override关键字:

public class ChildOne : ParentClass {
    public override void foo() {
        Debug.Log("Child one called!");
    }
}

public class ChildTwo : ParentClass {
    public override void foo() {
        Debug.Log("Child two called!");
    }
}
使用ArrayList,可以通过以下方式调用foo方法:

ArrayList children = new ArrayList();
children.Add(new ChildOne());
(children[0] as ParentClass).foo(); // will display "Child one called!"
请注意,子项[0]返回一个对象。必须将此对象强制转换为ParentClass才能调用foo方法

我的最后一个建议是使用列表而不是ArrayList。列表是强类型的(您不必强制转换任何内容),并且速度更快,因为没有装箱/取消装箱。现在没有很多理由(如果有的话)使用ArrayList

var children = new List<ParentClass>();
children.Add(new ChildOne());
children[0].foo(); // will display "Child one called!"
var children=newlist();
添加(新的ChildOne());
子项[0]。foo();//将显示“已调用子对象!”

如果可以,可以使用多态性而不是隐藏父函数的foo函数

为了实现此结果,我们可以将父类转换为foo方法虚拟,以便在子类中重写它:

public class ParentClass {
    public virtual void foo() {
        Debug.Log("Parent called!");
    }
}
然后在children类中,我们将new关键字替换为override关键字:

public class ChildOne : ParentClass {
    public override void foo() {
        Debug.Log("Child one called!");
    }
}

public class ChildTwo : ParentClass {
    public override void foo() {
        Debug.Log("Child two called!");
    }
}
使用ArrayList,可以通过以下方式调用foo方法:

ArrayList children = new ArrayList();
children.Add(new ChildOne());
(children[0] as ParentClass).foo(); // will display "Child one called!"
请注意,子项[0]返回一个对象。必须将此对象强制转换为ParentClass才能调用foo方法

我的最后一个建议是使用列表而不是ArrayList。列表是强类型的(您不必强制转换任何内容),并且速度更快,因为没有装箱/取消装箱。现在没有很多理由(如果有的话)使用ArrayList

var children = new List<ParentClass>();
children.Add(new ChildOne());
children[0].foo(); // will display "Child one called!"
var children=newlist();
添加(新的ChildOne());
子项[0]。foo();//将显示“已调用子对象!”

作为动力学状态,最好的解决方案是使
ParentClass.foo()
虚拟。但是,如果您不能修改父类,那么您将需要其他东西

作为反射的替代方案,您可以尝试以下方法:

foreach (var child in children) {
    if (child is ChildOne) {
        ((ChildOne)child).foo();
    } else if (child is ChildTwo) {
        ((ChildTwo)child).foo();
    } else {
        // whatever you need to do to handle an unknown child
    }
}
正如Noob指出的那样,对于许多儿童课程来说,这可能会很难实现。另一种选择是使用接口,如下所示:

public interface IFoo {
    void foo();
}

public class ChildOne : ParentClass, IFoo {
    public new void foo() {
        Debug.Log("Child one called!");
    }
}

public class ChildTwo : ParentClass, IFoo {
    public new void foo() {
        Debug.Log("Child two called!");
    }
}
那么这个,

foreach (var child in children) {
    if (child is IFoo) {
        ((IFoo)child).foo();
    } else {
        // handle unknown child
    }
}

作为动力学状态,最好的解决方案是使
ParentClass.foo()
virtual。但是,如果您不能修改父类,那么您将需要其他东西

作为反射的替代方案,您可以尝试以下方法:

foreach (var child in children) {
    if (child is ChildOne) {
        ((ChildOne)child).foo();
    } else if (child is ChildTwo) {
        ((ChildTwo)child).foo();
    } else {
        // whatever you need to do to handle an unknown child
    }
}
正如Noob指出的那样,对于许多儿童课程来说,这可能会很难实现。另一种选择是使用接口,如下所示:

public interface IFoo {
    void foo();
}

public class ChildOne : ParentClass, IFoo {
    public new void foo() {
        Debug.Log("Child one called!");
    }
}

public class ChildTwo : ParentClass, IFoo {
    public new void foo() {
        Debug.Log("Child two called!");
    }
}
那么这个,

foreach (var child in children) {
    if (child is IFoo) {
        ((IFoo)child).foo();
    } else {
        // handle unknown child
    }
}

我相信
(儿童[0]作为父类)。foo()
将调用
ParentClass
foo()
方法。你让我怀疑自己!我测试了它,但它没有调用ParentClass.foo()。您的测试是什么样子的?我的@Crowcoder是的,你仍然在使用问题中的代码,而不是我答案中的代码。你需要使用“virtual”和“override”关键字,去掉“new”关键字。我会(在可能的时候)把你的票还给你。考虑更明确些。我相信<代码>(儿童[0 ]为ParentClass)。Foothe()<代码>将调用<代码> ParentClass <代码> <代码>脚注()/代码>方法。你让我怀疑自己!我测试了它,但它没有调用ParentClass.foo()。您的测试是什么样子的?我的@Crowcoder是的,你仍然在使用问题中的代码,而不是我答案中的代码。你需要使用“virtual”和“override”关键字,去掉“new”关键字。我会(在可能的时候)把你的票还给你。考虑更明确一些。如果有很多子类,我可以看到这是一个疯狂的声明。对一对夫妇来说似乎没问题,但如果他有几百个呢?同意。我添加了另一个选项。我可以看到这是一个有很多子类的疯狂if语句。对一对夫妇来说似乎没问题,但如果他有几百个呢?同意。我正在添加另一种选择。