加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 07:58:44 所属栏目:百科 来源:网络整理
导读:在使用带继承的泛型约束时,我遇到了一些非常令人惊讶的事情.我有一个重载的方法Foo与参数不同 – 基本或派生类实例.在这两种情况下,它通常只是将实例传递给第二对重载方法 – Bar. 当我用基类实例调用Foo时,会调用基类的Bar重载.当我使用派生类实例调用Foo时
在使用带继承的泛型约束时,我遇到了一些非常令人惊讶的事情.我有一个重载的方法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的调用绑定到最不具体的重载,即使在编译时已知所有更具体类型的调用.为什么会这样,这种行为的原因是什么?哪部分规格定义了这个?

解决方法

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

泛型不是模板.通用方法编译一次,它们的行为是针对“最通用”的情况(在本例中为Animal).这与C样式模板不同,其中模板是按类型为每个特化分别编译的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读