让我们考虑一个示例层次结构
class BaseClass{}
class ChildClass1 : BaseClass{}
class ChildClass2 : BaseClass{}
现在我有一个类型为BaseClass的通用列表
List<BaseClass> sampleList = new List<BaseClass>();
在此列表中,我同时添加了ChildClass1
和ChildClass2
的对象。
现在访问这些对象时,我想对不同类型的对象执行不同的操作。
我可以使用if-else
并检查对象是否为所需类型来轻松实现这一目标。
class SampleClass
{
int Property{get;set;}
List<BaseClass> sampleList = new List<BaseClass>();
void DoCalculations()
{
foreach(var obj in sampleList)
{
if(obj is ChildClass1){//Do something to this.Property}
else if(obj is ChildClass2){//Do Somethingto this.Property}
}
}
}
但是由于复杂性和性能问题,我想避免使用if-else
或switch
(我的实际情况包含大量派生类)。
因此,为了解决这种情况,我想出了一种方法,可以使用名称相同但类型不同的重载方法(每个派生类型均适用)。
我想到了以某种方式迭代并将BaseClass强制转换为ChlidClass对象,并将其传递给DoSomething()
方法,而重载本身将照顾要执行的操作。但是,我无法从BaseClass获取ChildClass类型的对象来动态工作。
我尝试过的是:
class SampleClass
{
int Property{get;set;}
List<BaseClass> sampleList = new List<BaseClass>();
public void DoCalculations()
{
foreach(var entry in sampleList)
{
Type type = entry.GetType();
var obj = entry as type; //getting error here
this.DoSomething(obj);
}
}
private void DoSomething(ChildClass1 obj){//Do something to this.Property}
private void DoSomething(ChildClass2 obj){//Do something to this.Property}
}
在上面的代码中,我仅显示了一个属性int Property{get;set;}
的使用,但在我的实际情况下,请考虑使用多个属性。
有什么方法可以满足我的需求?
编辑: 如以下注释中所提到的,以及在BaseClass()中具有DoSomething()方法并在ChildClasses中覆盖它们的一些答案,在我的情况下,这可能实际上不起作用,因为DoSomething()与在其中定义的类的全局字段属性一起使用不是特定于ChildClass的对象。
答案 0 :(得分:5)
请考虑使您的类BaseClass
abstract
并为其提供一个abstract
方法。
类型ChildClass1
和ChildClass2
都将被强制覆盖DoSomething()
如果由于某种原因而无法使BaseClass
抽象,则还可以使方法virtual
然后在override
和ChildClass1
中ChildClass2
< / p>
抽象方法:
abstract class BaseClass
{
public abstract void DoSomething();
}
class ChildClass1 : BaseClass{
public override void DoSomething()
{
Console.WriteLine("Impl. 1");
}
}
class ChildClass2 : BaseClass{
private string _someRandomAttribute = "Impl. 2";
public override void DoSomething()
{
Console.WriteLine(_someRandomAttribute);
}
}
虚拟方法:
class BaseClass
{
public virtual void DoSomething()
{
Console.WriteLine("Base implementation for types that don't override DoSomething()");
}
}
class ChildClass1 : BaseClass{
public override void DoSomething()
{
Console.WriteLine("Impl. for type ChildClass1");
}
}
class ChildClass2 : BaseClass{
public override void DoSomething()
{
Console.WriteLine("Impl. for type ChildClass2");
}
}
完成此操作后,您将可以执行以下操作:
foreach(var obj in sampleList)
{
obj.DoSomething();
}
答案 1 :(得分:3)
您应在DoSomething
中使BaseClass
成为虚拟方法,并让派生类适当覆盖它。然后,您可以在任何实例上简单地调用DoSomething
:
class BaseClass
{
virtual void DoSomething() { ... }
}
class Child1 : BaseClass
{
override void DoSomething() { Console.WriteLine("Child1"); }
}
现在,您无需检查类型,因为实例知道其类型,因此运行时知道要调用的覆盖:
foreach(BaseClass obj in sampleList)
{
obj.DoSomething();
}
如果您想强制派生类来实现它,甚至可以使用DoSomething
方法abstract
。恕我直言,除非您希望能够实例化BaseClass
,否则这很有意义。