使用Func<;T>;在C#中

本文关键字:gt lt 使用 Func | 更新日期: 2023-09-27 18:27:42

上周我遇到了一个有趣的问题,我不确定我是否真正理解以下代码的多态性。我基于自己编写的一些代码创建了这个示例。

基本设置

  • 我有一个班"驯兽师",知道如何训练动物
  • 我用它作为基类,并创建了一个子类"DogTrainer",它知道如何只训练狗
  • 我使用超类作为返回类型创建了一个函数指针
  • 然后我调用这个函数,得到子类"DogTrainer"的一个新实例
  • 然后,我调用从函数指针返回的实例的"Train"方法
  • "训练"方法调用"训练器"-"训练"法,而不是预期的"DogTrainer"-"培训"法

这是代码

// Does not work as expected
// Calls the Trainer Train not the DogTrainer Train
var getTrainer = new Func<Trainer>(() => new DogTrainer(new Dog()));
var funcTrainer = getTrainer();
Console.WriteLine(funcTrainer.Train());

现在,如果我使用接口作为返回类型,它确实按预期工作。"if"我将接口直接标记在"DogTrainer"子类上

// Works as expected 
var getITrainer = new Func<ITrainer>(() => new DogTrainer(new Dog()));
var funcITrainer = getITrainer();
Console.WriteLine(funcITrainer.Train());

如果我在子类上没有接口,它就不能按预期工作。参见示例

// Does not work as expected 
// Calls the Trainer Train not the Dog Trainer Train
var getITrainerWithNoInterface = new Func<ITrainer>(() => new DogTrainerWithNoInterface(new Dog()));
var funcITrainerWithNoInterface = getITrainerWithNoInterface();
Console.WriteLine(funcITrainerWithNoInterface.Train());

如果有人能让我知道我在这里错过了什么,这种行为不是我所期望的。当我在代码中发现这个错误时,我能够解决它,我在这里寻找的是发生这种情况的"原因"。

这里是DogTrainerWithNoInterface,它可能是谜题(Trainer:ITrainer)的主要部分

public class DogTrainerWithNoInterface : Trainer
{
    public DogTrainerWithNoInterface(IAnimal animal)
        : base(animal)
    { }
    public new string Train()
    {
        return $"Speak Ubu, Speak : {Animal.Speak()}";
    }
}

使用Func<;T>;在C#中

注意:这个答案纯粹是为了描述由于不适合注释而出现的"新"问题。请忽略投票,因为它不能完全回答他的问题

OP链接中的样本:

public class DogTrainer : Trainer, ITrainer
{
    public DogTrainer(IAnimal animal)
        : base(animal)
    { }
    public new string Train()
    {
        return $"Speak Ubu, Speak : {Animal.Speak()}";
    }
}

在声明方法/属性时不要使用new。在底座上制作virtual,然后制作override。你正在做的是将方法隐藏在你的基础上。

您只能在使用特定类型(DogTrainer)时调用new方法。对基的任何向下转换都将调用它的方法,即使用声明为TrainerITrainer的变量。

知道何时使用覆盖和新关键字(C#编程指南)