C# Can';无法获取要执行的重写方法

C# Can';无法获取要执行的重写方法,c#,inheritance,C#,Inheritance,我的父类定义如下: namespace Models { public class GameState { public Player ThisPlayer { get; set; } } public class Player { public int Id { get; set; } public Player(int id) { Id = id;

我的父类定义如下:

namespace Models
{
    public class GameState
    {
        public Player ThisPlayer { get; set; }
    }

    public class Player
    {
        public int Id { get; set; }

        public Player(int id)
        {
            Id = id;
        }

        public void TakeTurn(GameState state)
        {
            Console.WriteLine("In Models.Player.TakeTurn");
        }
    }
}
子类定义为:

namespace Subs
{
    public class GameState : Models.GameState
    {
        public void TakeTurn()
        {
            ThisPlayer.TakeTurn(this);
        }
    }

    public class Player : Models.Player
    {
        public Player(int id) : base(id) { }

        public virtual void TakeTurn(GameState state)
        {
            base.TakeTurn(state);
            Console.WriteLine("In Subs.Player.TakeTurn");
        }
    }

    public class MachinePlayer : Player
    {
        public MachinePlayer(int id) : base(id) { }

        public override void TakeTurn(GameState state)
        {
            Console.WriteLine("In Subs.MachinePlayer.TakeTurn");
        }
    }
}
该计划包括:

Subs.MachinePlayer machinePlayer = new Subs.MachinePlayer(1);
Subs.GameState state = new Subs.GameState();
state.ThisPlayer = machinePlayer;
state.TakeTurn();
问题是,即使玩家是MachinePlayer,MachinePlayer TakeTurn方法也不会执行,输出只是:

In Models.Player.TakeTurn

我希望每个球员轮流上场。有些玩家是人类(Subs.Player)或机器人(Subs.MachinePlayer)。我做错了什么?谢谢。

玩家轮流方法不是虚拟的,你需要改变它,它应该可以工作。也可以在需要的地方重写。

在继承的类中,名为
TakeTurn
(两个重载)实际上有两个方法:

注意参数的类型。执行此操作时:

ThisPlayer.TakeTurn(this);
你真的在这样做:

((Models.Player)ThisPlayer).TakeTurn((Models.GameState)this);
为什么??因为
ThisPlayer
静态类型是
Models.Player
,它只有一个(第一个)方法本身是而不是
virtual
。没有过载解决方案或虚拟调度。唯一的候选者是在基类上声明的候选者

通过查看IL来验证这一点:

method public hidebysig 
    instance void TakeTurn () cil managed 
{
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: call instance class Models.Player Models.GameState::get_ThisPlayer()
    IL_0006: ldarg.0
    IL_0007: callvirt instance void Models.Player::TakeTurn(class Models.GameState) // <-- HERE
    IL_000c: ret
}
方法公共隐藏
实例void TakeTurn()cil托管
{
.maxstack 8
IL_0000:ldarg.0
IL_0001:调用实例类模型。玩家模型。游戏状态::get_ThisPlayer()
IL_0006:ldarg.0

IL_0007:callvirt实例void Models.Player::TakeTurn(类模型.游戏状态)//
TakeTurn
方法在
模型中。Player
不是一个
虚拟的
并且不会被覆盖,你知道你有两个名为Player的类,对吧?这真是让人困惑。我更新了示例,使方法虚拟并重命名子类。现在它告诉我它找不到覆盖的方法。我意识到了签名必须完全匹配,但是我将无法访问子游戏状态方法。正确的方法是什么?请回滚您对该问题的编辑。现在完全不同,并且会使给出的答案无效。这不是编辑的目的。针对新问题提出新问题,如果答案明确,请投票/接受答案d您的问题我将子层和机器层方法签名更改为:public override void TakeTurn(Models.GameState)这意味着如果我想访问SubGameState中的属性或方法,我需要将state参数强制转换为SubGameState。除非有人能想出更好的方法,否则我可以接受。在这种情况下,你基本上违反了LSP。如果你真的需要,你可以选择键入check并强制转换。你可以通过一些泛型获得它在我看来,这太过分了,在没有看到你的充分使用之前,我真的不能提出这个建议。一个新的问题是合适的。我回答了你原来的问题,你不能改变它,让它完全不同
method public hidebysig 
    instance void TakeTurn () cil managed 
{
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: call instance class Models.Player Models.GameState::get_ThisPlayer()
    IL_0006: ldarg.0
    IL_0007: callvirt instance void Models.Player::TakeTurn(class Models.GameState) // <-- HERE
    IL_000c: ret
}