让我们考虑一个示例层次结构
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;}
的使用,但在我的实际情况中,考虑了多个属性。有什么方法可以达到我的需要吗?
编辑:正如下面的评论和一些答案中所提到的,让DoSomething((在BaseClass((中成为一个方法并在ChildClass中覆盖它们,在我的情况下,这可能实际上不起作用,因为DoSometing((与它所定义的类的全局字段属性一起工作。它不是ChildClass对象特有的。
考虑将类设为BaseClass
abstract
,并给它一个abstract
方法。ChildClass1
和ChildClass2
两种类型都将被强制覆盖DoSomething()
如果由于某种原因无法使BaseClass
抽象,您也可以在ChildClass1
和ChildClass2
中使方法virtual
和override
抽象
抽象方法:
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();
}
您应该使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
。这是有意义的IMHO,除非你想实例化BaseClass
。