gpt4 book ai didi

c# - 具有继承和通用约束的两步方法解析

转载 作者:太空狗 更新时间:2023-10-29 20:28:38 26 4
gpt4 key购买 nike

在使用继承的通用约束时,我遇到了一些非常令人惊讶的事情。我有一个重载方法 Foo 与参数不同 - 基类或派生类实例。在这两种情况下,它通常只是将实例传递给第二对重载方法 - Bar

当我用基类实例调用 Foo 时,将调用基类的 Bar 重载。当我用派生类实例调用 Foo 时,将调用派生类的 Bar 重载。这是明确的和意料之中的。

但是当我尝试将 Foo 方法合并到使用泛型和约束的单个 GenericFoo 时,方法的解析不同 - T 被正确解析,但仅是基类调用了 Bar 的重载。

public class Animal { }
public class Cat : Animal { }

public class AnimalProcessor
{
public static void Foo(Animal obj)
{
Console.WriteLine("Foo(Animal)");
Bar(obj);
}

public static void Foo(Cat obj)
{
Console.WriteLine("Foo(Cat)");
Bar(obj);
}

// new generic method to replace the two above
public static void GenericFoo<T>(T obj)
where T : Animal
{
Console.WriteLine("Foo(generic)");
Bar(obj);
}

public static void Bar(Animal obj)
{
Console.WriteLine("Bar(Animal)");
}

public static void Bar(Cat obj)
{
Console.WriteLine("Bar(Cat)");
}
}

测试代码 - 非泛型旧方法的前两个案例,新泛型方法的最后两个案例。

Console.WriteLine("Animal()");
AnimalProcessor.Foo(new Animal());
Console.WriteLine();

Console.WriteLine("Cat()");
AnimalProcessor.Foo(new Cat());
Console.WriteLine();

Console.WriteLine("Animal()");
AnimalProcessor.GenericFoo(new Animal());
Console.WriteLine();

Console.WriteLine("Cat()");
AnimalProcessor.GenericFoo(new Cat());
Console.ReadLine();

结果 - 注意 Bar 中解析的类型差异:

Animal()
Foo(Animal)
Bar(Animal)

Cat()
Foo(Cat)
Bar(Cat)

Animal()
Foo(generic)
Bar(Animal)

Cat()
Foo(generic)
Bar(Animal)

看起来编译器将所有来自 GenericFoo 的调用绑定(bind)到最不具体的重载,即使所有更具体类型的调用在编译时都是已知的。为什么会这样,这种行为的原因是什么?规范的哪一部分定义了这一点?

最佳答案

根据 OP 的要求,将评论重新发布为答案:

泛型不是模板。通用方法编译一次,它们的行为适用于“最通用”的情况(在本例中为 Animal。)这与 C++ 样式模板不同,在 C++ 样式模板中,模板是按类型为每个专门化单独编译的。

关于c# - 具有继承和通用约束的两步方法解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8232400/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com