You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#重写接口方法使用派生接口参数报错的原因及解决方案

接收接口类型参数的方法支持派生类型实例的方案问题

现有代码定义

首先定义了两层玩家接口,存在继承关系:

public interface IPlayer {
    public List<Card> LoseCards();
}

public interface IPlayer_WithPersonalDeck : IPlayer {
    public void AddCardsToPersonalDeck(List<Card>);
}

在此基础上定义了泛型命令接口,以及面向IPlayer的命令基类:

public interface ICommands<T> {
    public Object? execute (T);
    public Object? execute (T, T);
}

public class BasePlayerCommands : ICommands<IPlayer> {
    public virtual Object? execute (IPlayer) { throw new NotSupportedException(); }
    public virtual Object? execute (IPlayer executor, IPlayer target) { throw new NotSupportedException(); } 
}

编译异常场景

尝试实现特定命令类,完成「从目标玩家处拿牌并加入执行者个人牌组」的逻辑,代码如下:

public class TakeCardsFromPlayer_AndAddToDeckCommand : BasePlayerCommands {
    public override List<Card> execute(IPlayer_WithPersonalDeck executor, IPlayer target) {
        return executor.AddCardsToPersonalDeck(target.LoseCards());
    }
}

上述代码无法通过编译,错误提示为:TakeCardsFromPlayer_AndAddToDeckCommand中找不到可重写的匹配execute方法。

疑问与诉求

报错的直接原因是重写方法时将第一个参数类型写为派生接口IPlayer_WithPersonalDeck而非基接口IPlayer,但按照里氏替换原则,所有实现IPlayer_WithPersonalDeck的类型必然实现了IPlayer接口,要求传入IPlayer的方法理应兼容该派生类型,需要明确该写法不符合预期的底层原因,以及对应的类型安全可行解法。

方案约束:尽量避免直接实现ICommands<IPlayer_WithPersonalDeck>,因为并非所有玩家命令都要求参与的玩家拥有个人牌组。

当前使用的临时方案是在execute方法内部将IPlayer类型参数强制转换为目标派生接口,但该方案不满足类型安全:任意IPlayer实例都可能被传入,若传入实例未实现对应派生接口会抛出运行时错误,对调用方的约束不足。


内容的提问来源于stack exchange,提问作者Venwin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 15:33:22