好的,我有一些从基类派生的不同对象,我把它们放在一个列表中。我想遍历列表并将每个推送到一个方法。我对每个类型的签名都有单独的方法,但编译器抱怨。有人可以解释原因吗?这是一个使用泛型的机会,如果是的话,怎么样?
class Base { }
class Level1 : Base { }
class Level2 : Level1 { }
...
List<Base> oList = new List<Base>();
oList.Add(new Level1());
oList.Add(new Level2());
...
...
foreach(Base o in oList)
{
DoMethod(o);
}
...
void DoMethod(Level1 item) { }
void DoMethod(Level2 item) { }
我做错了什么?
答案 0 :(得分:7)
重载在编译时解决 - 并且您没有DoMethod(Base item)
方法 - 因此无法解析调用。离开列表和循环,你有效地写作:
Base o = GetBaseFromSomewhere();
DoMethod(o);
编译器必须找到一个名为DoMethod
的方法,该方法适用于Base
类型的单个参数。没有这样的方法,因此失败了。
这里有几个选项:
您可以使用o
或as
:
is
再次,这非常难看
答案 1 :(得分:2)
重载方法使用变量的静态类型而不是运行时类型。
您想使用inheritence和覆盖。
class Base { public virtual void DoMethod() { /* ... */ } }
class Level1 : Base { public override void DoMethod() { /* ... */ } }
class Level2 : Level1 { public override void DoMethod() { /* ... */ } }
答案 2 :(得分:1)
调用哪个方法是在编译时而不是运行时确定的,因此编译器无法知道要调用哪个方法。你有2个选择: 切换对象的类型并调用适当的方法,或 如果您使用的是.NET 4,请使用type dynamic。
foreach(dynamic o in oList)
{
DoMethod(o);
}
答案 3 :(得分:1)
您没有DoMethod(基本项)方法。重载不是多态的。这通常通过使用虚拟方法完成:
class Base {
public virtual void DoMethod() {...}
}
class Level1 : Base {
public override void DoMethod() {...}
}
// etc..
foreach(Base o in oList)
{
o.DoMethod();
}
答案 4 :(得分:1)
在您的foreach循环中,o
的类型为Base
,而DoMethod
重载都没有Base
个实例。如果可能,您应该将DoMethod
移至Base
并在两个子类中覆盖它:
public class Base
{
public virtual void DoMethod() { ... }
}
答案 5 :(得分:1)
要扩展Mark的答案,DoMethod应该是Base中的虚拟方法,您可以在列表中的每个项目上调用它。
答案 6 :(得分:0)
我不知道所有的细节,但如果它真的不适合继承你可以使用接口。
声明接口,在每个类上实现它,然后你就可以直接转换到接口并从那里运行函数。我的C#有点不稳定,但有点像,
Interface IMethodizable
{
void DoMethod();
}
class Level1 : IMethodizable {
void DoMethod(){
//insert code here
}
}
class Level2 : IMethodizable {
void DoMethod(){
//insert code here
}
}
如果这个类的唯一共同点是那个方法,那么效果特别好。这与在基类中使用虚拟化方法并覆盖它非常相似。所以这种模式只有在你不应该继承时才会更好,或者DoMethod也必须在不继承base等的其他对象上运行。
答案 7 :(得分:0)
由于C#7.0模式匹配是另一种选择。
有关更多信息,请参见MSDN。 您的代码想要:
switch(o)
{
case Level2 level2: Do(level2); break;
case Level1 level1: Do(level1); break;
case Base @base: Do(@base); break;
default: ...
case null: ...
}