通用类型何时确定?会受到影响吗?

时间:2011-03-01 11:00:37

标签: .net methods c#-2.0 generics

我一直在玩仿制药,我一直在看一些奇怪的东西。我希望你们有解释!为了使一切更容易,我把“问题”放在一个例子中:

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

2 个答案:

答案 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推迟解析为运行时(注意;不是理想使用动态,但它有效)