【发布时间】:2020-08-17 14:15:48
【问题描述】:
多年后我正在重温我的 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(),因为你没有将Tthing限制为Root,所以它默认使用object的方法。编译器不知道你的Tthing有一个新的ToString()方法。 -
因为你使用的是
new,所以调用ToString的默认实现是行不通的。如果你想强制你的派生类覆盖ToString,你应该使用public override abstract string ToString(); -
@CodeCaster:AFAIK 编译器确实知道,这是因为根目录中 ToString() 中的“新”。注释掉'public class NamedThing
中的ToString(),你会得到编译器错误“'NamedThing '没有实现继承的抽象成员'Root.ToString()'”。 -
@DavidG:成功了!谢谢
-
谨慎使用会员隐藏功能。
标签: c# generics visual-studio-2019 vtable c#-8.0