泛型类型何时确定?可以影响吗?

发布于 2024-10-19 14:38:20 字数 1502 浏览 7 评论 0原文

我一直在研究泛型,并且看到了一些奇怪的东西。希望大家给个解释!为了让一切变得更容易,我将“问题”放入一个例子中:

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.Dog

I've been playing around with generics and I've been seeing some weird stuff. I hope you guys have an explanation! To make everything easier I've put the "problem" into an example:

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();
        }
    }
}

So, I have two animals in my Lab: a dog and a bird. When I "kick" those animals they'll make a sound. The printer will print the sound and the type of animal. When I run the program it prints:

Kick bird:
Lab.Animal says 'Tweet!'

Kick dog:
Lab.Animal says 'Bark, bark! I'll bite you!'

Print kick dog:
Lab.Dog says 'Bark, bark! I'll bite you!'

Why does the first kick of the dog tell me it is of the type Lab.Animal?
And... how can I get it to return Lab.Dog?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甜宝宝 2024-10-26 14:38:20

狗的第一脚告诉您类型参数的编译时类型是 Lab.Animal。换句话说,您的 Animal.Kick 方法是有效的:

Printer.Print<Animal>(this, Sound);

类型参数不是多态确定的 - 它们是在编译时确定的。当一个调用的类型参数实际上是调用上下文的类型参数时,情况会变得更加复杂,但它本质上是同一类东西。

要使其显示 Lab.Dog,您必须获取对象的实际执行时类型,例如使用

obj.GetType().FullName

The first kick of the dog tells you that the compile-time type of the type argument was Lab.Animal. In other words, your Animal.Kick method is effectively:

Printer.Print<Animal>(this, Sound);

Type arguments aren't determined polymorphically - they're determined at compile-time. It becomes more complicated when the type argument of one call is actually the type parameter of the calling context, but it's fundamentally the same kind of thing.

To make it say Lab.Dog, you'd have to get the actual execution-time type of the object, e.g. using

obj.GetType().FullName
夏夜暖风 2024-10-26 14:38:20

通常,泛型是在编译时确定的,但它们也是运行时功能。在这种情况下,您使用的是泛型类型推断,它使用变量等来推断类型。

在该方法中:

    public void Kick()
    {
        Printer.Print(this, Sound);
    } 

在此上下文中,对 this 的所有已知信息是它必须是 Animal,因此存在一个隐式 Anmial,即 Printer.Print。 (this, Sound)

其他选项:

  • 使用 GetType() 查找对象的实际类型,
  • 使用 dynamic 将解析推迟到运行时(注意;不是理想使用动态,但它有效)

Normally, generics are determined at compile time, but they are also a runtime feature. In this case you are using generic type inference, which uses the variables etc to infer type.

In the method:

    public void Kick()
    {
        Printer.Print(this, Sound);
    } 

all that is known of this in this context is that it must be Animal so there is an implicit Anmial, i.e. Printer.Print<Animal>(this, Sound)

Other options:

  • use GetType() to find the actual type of the object
  • use dynamic to defer resolution to runtime (note; not an ideal use of dynamic, but it works)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文