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语句。对一对夫妇来说似乎没问题,但如果他有几百个呢?同意。我正在添加另一种选择。