C#可以强制编译时类型,但在运行时匹配方法时可以动态识别子类吗 TL/DR: SpecificType是GeneralType的子类 GeneralType和SpecificType都具有相同名称和参数“doSomething()”的方法。GeneralType的其他子类不需要用这个名称定义自己的方法,只需要隐式地定义GeneralType的实现 问题是:您有一个SpecificType对象作为GeneralType传递给您,当您调用它的doSomething()方法时,它调用GeneralType.doSomething()而不是SpecificType.doSomething(),因为编译器通常只关心编译时声明的类型,而不关心运行时的实际类型 解决方案:将GeneralType.doSomething()声明为“虚拟”,并将SpecificType.doSomething()声明为“覆盖” 原始场景、示例代码和问题如下。

C#可以强制编译时类型,但在运行时匹配方法时可以动态识别子类吗 TL/DR: SpecificType是GeneralType的子类 GeneralType和SpecificType都具有相同名称和参数“doSomething()”的方法。GeneralType的其他子类不需要用这个名称定义自己的方法,只需要隐式地定义GeneralType的实现 问题是:您有一个SpecificType对象作为GeneralType传递给您,当您调用它的doSomething()方法时,它调用GeneralType.doSomething()而不是SpecificType.doSomething(),因为编译器通常只关心编译时声明的类型,而不关心运行时的实际类型 解决方案:将GeneralType.doSomething()声明为“虚拟”,并将SpecificType.doSomething()声明为“覆盖” 原始场景、示例代码和问题如下。,c#,overriding,C#,Overriding,假设您有一个chess实现,其中: class ChessPiece { public void promoteIfPawnAndPromoted(ChessPieceType newType) { return; // Do nothing } } class Pawn : Chesspiece { // This is not `override` nor `new`: public void promoteIfPawnAndPromot

假设您有一个chess实现,其中:

class ChessPiece {

    public void promoteIfPawnAndPromoted(ChessPieceType newType) {
        return; // Do nothing
    }
}

class Pawn : Chesspiece {

    // This is not `override` nor `new`:
    public void promoteIfPawnAndPromoted(ChessPieceType newType) {
        /* Do stuff */
    }
}
  • 在其生命周期中,
    典当
    对象由一个工厂方法创建,其声明的返回类型为
    棋子
    ,然后作为
    棋子
    ,或
    列表
    哈希集
    棋子[]
    的元素在不同点存储和传递

  • 典当对象只能是
    棋子
    典当
    。例如,它永远不会是
    字符串
    bool
    。如果我试图将它用作棋子或棋子之外的任何东西,我希望编译器大声抱怨

  • 然而,在运行时,如果我调用恰好是棋子的
    棋子的
    promoteifpawandpromoted()
    方法,我希望它使用棋子的方法,而不是
    棋子的方法

对于当前版本的C#,有没有一种方法可以声明类以便

  • 保留强编译时类型检查(即,变量或参数最终可能是典当、车、骑士或任何其他
    棋子
    …但它绝对不会是字符串或整数)

  • 然而,在编译时要认识到任何给定的
    ChessPiece
    对象都可能与promoteIfpawandPromoted()的两个可能变体相匹配,并询问ChessPiece实例本身(在运行时)它应该绑定到哪一个

我很确定现在有一种官方的“好”方法可以在C#中简洁地声明这一点(相对于通过instanceof进行手动运行时if/then测试),但我不太确定它是什么。我来自Java,对于“dynamic”和“var”之间的区别(更不用说C#method声明中可能包含的其他内容,比如用“virtual”声明超类方法与用“new”声明子类方法之间的区别)我仍然不确定。经验方面,我在Java方面有足够的经验认识到我在流沙的雷区中跋涉,但在C#方面没有足够的经验来避免沉没或爆炸

我可能错了,但就我现在的理解

  • 如果我将该类型声明为“dynamic”,那么我就完全放弃了编译时类型检查baby。我不能保证某些东西可能是一个棋子,但永远&绝对是一个棋子,永远不可能是一根弦

  • 如果我将类型声明为“var”,编译器仍将使用静态绑定。。。它只是在编译时自动执行。因此,如果它看到我的'var'总是被传递给一个棋子,它仍然会静态地绑定到棋子的方法,而不是等到运行时才看到这个棋子是否真的是一个棋子

  • 我的直觉是,将超类方法声明为“虚拟”可能是朝着正确方向迈出的一步

  • 目前,我还不能完全理解在超类中重写虚拟方法的上下文中将重写方法声明为“new”与“override”之间的区别


更新#1(错误): 根据[,看起来我所要做的就是:

public virtual void promoteIfPawnAndPromoted(ChessPieceType newType) {
    return;
}
public virtual void promoteIfPawnAndPromoted(ChessPieceType newType) {
    return;
}
然后在当押中声明:

public new void promoteIfPawnAndPromoted(ChessPieceType newType) {
    // Pawn-specific implementation...
}
public override void promoteIfPawnAndPromoted(ChessPieceType newType) {
    // Pawn-specific implementation...
}
这不起作用。在标识为棋子的棋子上调用
promoteifpawandpromoted(newType)
(用
virtual
声明的棋子方法,用
new
声明的棋子方法)仍然会导致调用“棋子”变体,而不是典当的变体

更新#2(正确): 在Pawn的方法声明中将“new”替换为“override”似乎起到了作用。在声明为棋子的Pawn上调用PromoteIfpawandPromoted(newType)现在似乎是在调用Pawn变量&而不是棋子变量……但我还不能100%相信这是完整的解决方案(这些年来,我经历了太多的事情,以至于我现在开始关心某个工作解决方案是否“正式正确”,而不是“没有错误的编译,并且现在似乎可以工作”)

然后在当押中声明:

public new void promoteIfPawnAndPromoted(ChessPieceType newType) {
    // Pawn-specific implementation...
}
public override void promoteIfPawnAndPromoted(ChessPieceType newType) {
    // Pawn-specific implementation...
}

您在
Pawn
类中使用了错误的关键字。您想使用
覆盖
,因为它会导致v表查找查找派生类的实现。
新的
关键字有非常不同的用途


请参见

您在
Pawn
类中使用了错误的关键字。您想使用
覆盖
,因为它会导致v表查找找到派生类的实现。
新的
关键字有非常不同的用途


参见

看起来你想让代码< > />代码>改写<代码>这个<代码>(即<代码> /*一个棋子*/=新QueNe()/代码>当棋子到达棋盘的边缘时,你不能在C语言中这样做。你需要考虑一个不同的程序设计。我不认为任何<代码> ChessPiece < /代码> SU。