我一直在玩仿制药,我一直在看一些奇怪的东西。我希望你们有解释!为了使一切更容易,我把“问题”放在一个例子中:
namespace Lab
{
public class Animal
{
public Animal(string sound)
{
this.Sound = sound;
}
public string Sound { get; private set; }
public void Kick()
{
Printer.Print(this, Sound);
}
}
public class Dog : Animal
{
public Dog() : base("Bark, bark! I'll bite you!") { }
}
public class Printer
{
public static void Print<T>(T obj, string message)
{
System.Console.WriteLine("{0} says '{1}' \n", typeof(T).FullName.PadRight(10), message);
}
}
public static class Program
{
static void Main(string[] args)
{
Animal bird = new Animal("Tweet!");
Dog dog = new Dog();
System.Console.WriteLine("Kick bird:");
bird.Kick();
System.Console.WriteLine("Kick dog:");
dog.Kick();
System.Console.WriteLine("Print kick dog:");
Printer.Print(dog, dog.Sound);
System.Console.ReadLine();
}
}
}
所以,我的实验室里有两只动物:一只狗和一只鸟。当我“踢”那些动物时,它们会发出声音。打印机将打印声音和动物类型。当我运行该程序时,它会打印出来:
踢鸟: Lab.Animal说'推特!'
踢狗: Lab.Animal说'树皮,树皮!我会咬你的!“
打印踢狗: Lab.Dog说'树皮,树皮!我会咬你的!“
为什么狗的第一脚告诉我它属于Lab.Animal
类型?
并且...我怎样才能让它返回Lab.Dog
?
答案 0 :(得分:6)
狗的第一步告诉你,类型参数的编译时类型是Lab.Animal。换句话说,您的Animal.Kick
方法是有效的:
Printer.Print<Animal>(this, Sound);
类型参数不是多态确定的 - 它们是在编译时确定的。当一个调用的类型参数实际上是调用上下文的类型参数时,它变得更加复杂,但它基本上是同一类事物。
要说出Lab.Dog
,你必须得到对象的实际执行时类型,例如:使用
obj.GetType().FullName
答案 1 :(得分:3)
通常,泛型是在编译时确定的,但它们也是运行时功能。在这种情况下,您使用泛型类型推断,它使用变量等来推断类型。
在方法中:
public void Kick()
{
Printer.Print(this, Sound);
}
在此上下文中this
所知道的是它必须是Animal
所以有一个隐含的Anmial,即Printer.Print<Animal>(this, Sound)
其他选择:
GetType()
查找对象的实际类型dynamic
推迟解析为运行时(注意;不是理想使用动态,但它有效)