不能将派生类传递给接受泛型基类的方法

本文关键字:泛型 基类 方法 派生 不能 | 更新日期: 2023-09-27 18:06:51

大致有以下代码…

using System;
public interface ICommand<in TArgs>
    where TArgs : BaseArgs
{
    void Execute();
    void Execute(TArgs args);
}
public class BaseArgs
{ }
public abstract class BaseCommand<TArgs> : ICommand<TArgs>
    where TArgs : BaseArgs
{
    public void Execute()
    {
        var args = this.CreateArgs();
        this.Execute(args);
    }
    public void Execute(TArgs args)
    {
        this.GetData(args);
    }
    protected abstract void GetData(TArgs args);
    protected abstract TArgs CreateArgs();
}
public class ActualArgs : BaseArgs
{ }
public class ActualCommand : BaseCommand<ActualArgs>
{
    protected override void GetData(ActualArgs args)
    {
        var messenger = new Messenger(this.Execute);
        var m2 = new Messenger2(this);
    }
    protected override ActualArgs CreateArgs()
    {
        return new ActualArgs();
    }
}
public class Messenger
{
    public Messenger(Action caller)
    {
        caller();
    }
}
public class Messenger2
{
    public Messenger2(BaseCommand<BaseArgs> caller)
    {
        caller.Execute();
    }
}

理想情况下,我想使用Messenger2,但ActualCommand中的行抱怨它不能将ActualCommand<ActualArgs>转换为BaseCommand<BaseArgs>,我真的宁愿不将Messenger2声明为

new Messenger2<ActualCommand<ActualArgs>>(this)

不能将派生类传递给接受泛型基类的方法

这不起作用有两个原因:

  1. 只有泛型接口可以协变(或逆变)。参数是抽象基类,不是接口。
  2. 你的接口不是(也不能)协变。

假设这被编译了-你可以这样做:

BaseCommand<BaseArgs> command = new ActualCommand();
command.Execute(new SomeOtherArgsDerivedFromBaseArgs());

这个必须给你一些异常,因为ActualCommand不知道如何处理除了可以或可以强制转换到ActualArgs的东西之外的任何东西。