如何解决泛型防止虚函数调用?
多年后,我重新开始使用C#。我非常生锈,所以这可能不是我的编译器。
namespace ConsoleApp1 {
public abstract class Root {
// force me to implenent ToString() in subclasses
public abstract new string ToString();
}
public class Mammal : Root {
string m;
public Mammal(string mIn) { m = mIn; }
public override string ToString() => m;
}
// allow me to give a mammal a name:
public class NamedMammal : Root {
Mammal m; string name;
public NamedMammal(Mammal mIn,string nameIn) {
m = mIn; name = nameIn;
}
public override string ToString() =>
$"({m.ToString()} has name {name})";
}
// but I may want to name many things,so make
//the thing being named generic:
public class NamedThing<Tthing> : Root {
Tthing thing; string name;
public NamedThing(Tthing thingIn,string nameIn) {
thing = thingIn; name = nameIn;
}
public override string ToString() =>
$"({thing.ToString()} has name {name})";
}
// I can name tractors or planets if I want to Now
class Program {
static void Main() {
Mammal c = new Mammal("cow");
NamedMammal nm = new NamedMammal(c,"daisy");
Console.WriteLine(nm.ToString());
// output,as expected:
// (cow has name daisy)
Mammal f = new Mammal("fox");
NamedThing<Mammal> nt =
new NamedThing<Mammal>(f,"freddie");
Console.WriteLine(nt.ToString());
// not what I expected:
// (ConsoleApp1.Mammal has name freddie)
}
}
}
它显然不会丢失类型,因为它将其输出为“ ConsoleApp1.Mammal”,因此它知道它是哺乳动物,但它似乎并没有像我期望的那样调用ToString()。我猜想它正在调用最基础的对象ToString()而不是最基础的对象。
这是设计的吗,如果可以的话,有人可以给我一些指导,也许是关于如何处理此问题的想法,因为我不想手写这些样板。
解决方法
问题在于方法object.ToString()
和Root.ToString()
没有任何关联。这是您设计的。
在类NamedMammal
中,您期望类型为Mammal
的事物实现Root
。因此,编译器知道在给定实例上肯定存在方法Root.ToString()
。然后,在NamedMammal.ToString()
方法中,您将调用Root.ToString()
的{{1}}实现,因为它正在遮盖(而不是覆盖)Mammal
。
但是对于object.ToString()
类,您的事物不必实现NamedThing
,因此在方法Root.ToString()
中,调用NamedThing.ToString()
将调用{{ 1}}。这不会导致调用thing.ToString()
方法,因为它不是object.ToString()
的重要方法。
对此的一种解决方案是调节Root.ToString()
的类型参数以实现object.ToString()
,例如:
NamedThing
另一种解决方案是将Root
替换为
public class NamedThing<Tthing> : Root where Tthing : Root
{ .. }
与new
public abstract new string ToString();
通过这种方式,实现类型将覆盖override
,而不是不相关的相似命名方法。
但是请注意,至少需要第一个解决方案来强制与public abstract override string ToString();
一起使用的类型实现object.ToString()
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。