C# 当字典将抽象类作为值时,如何使用子类方法?

C# 当字典将抽象类作为值时,如何使用子类方法?,c#,dictionary,abstract-class,C#,Dictionary,Abstract Class,我正在做一个国际象棋游戏,我有一个名为cls_ChessPieces的抽象类,每个国际象棋都有一个类(cls_Pawn,cls_Knight,…) 我创建这个抽象类是因为我想将每一个棋子存储在字典中,棋盘上的位置作为键(字符串) 当我放置断点并检查piece1对象时,我可以看到它的类型(cls_Pawn)。但此类型仅在运行时提供给该对象。这使得无法调用CheckLegalMove()方法 这是我解决这个问题的方法,但我认为这不是正确的方法。每一个棋子类都需要大量的代码来完成,每次我想传递对象时,

我正在做一个国际象棋游戏,我有一个名为cls_ChessPieces的抽象类,每个国际象棋都有一个类(cls_Pawn,cls_Knight,…)

我创建这个抽象类是因为我想将每一个棋子存储在字典中,棋盘上的位置作为键(字符串)

当我放置断点并检查piece1对象时,我可以看到它的类型(cls_Pawn)。但此类型仅在运行时提供给该对象。这使得无法调用CheckLegalMove()方法

这是我解决这个问题的方法,但我认为这不是正确的方法。每一个棋子类都需要大量的代码来完成,每次我想传递对象时,我都需要再次执行此操作

if (piece1 is cls_Pawn)
   {
       cls_Pawn pawn= (cls_Pawn)piece1;
       pawn.CheckLegalMove();
   }
有没有一种简单的方法可以通过调用CheckLegalMove()方法从字典中获取cls_pawn类?我试图得到类型:

Type t = piece1.GetType();
但我不知道是否有可能用这种类型的演员

(t)piece1;
谢谢

编辑:

CheckLegalMove()可能不是一个好例子

public bool Promote()
    {
        // this is a method only this child class should have
    }

我猜每种类型的国际象棋项目都需要检查移动,所以在基类中声明方法:

public abstract class cls_ChessPieces
{
    public abstract bool CheckLegalMove();
}

class cls_Pawn : cls_ChessPieces
{
    public override bool CheckLegalMove()
    {
        // this is the method I want to call
    }
}
您将能够为从
cls\u Pawn
派生的每个类调用
CheckLegalMove()

bool ok = piece1.CheckLegalMove();

我猜每种类型的国际象棋项目都需要检查移动,所以在基类中声明方法:

public abstract class cls_ChessPieces
{
    public abstract bool CheckLegalMove();
}

class cls_Pawn : cls_ChessPieces
{
    public override bool CheckLegalMove()
    {
        // this is the method I want to call
    }
}
您将能够为从
cls\u Pawn
派生的每个类调用
CheckLegalMove()

bool ok = piece1.CheckLegalMove();

对于这个答案,我假设您不希望在
cls\u ChessPieces
基类中有一个抽象的
CheckLegalMove
方法。如果这不是问题,不要选择这种方法

方法1(不推荐) 您可以使用

var type = piece1.GetType();
然后检查每个反射类型是否通过执行以下操作定义了方法
CheckLegalMove()

var type = piece1.GetType();
var checkLegalMoveMethod = type.GetMethod("CheckLegalMove");

if(checkLegalMoveMethod != null)   
{  
    var result = (bool)checkLegalMoveMethod.Invoke(piece1);  
}
这是可行的,但前提是CheckLegalMove方法不包含任何参数

方法2(推荐方法) 您还可以做的一件事是引入另一个基类(同样,仅当您不想在
cls\u ChessPieces
中直接使用CheckLegalMove方法时才这样做)
,该基类定义如下:

class <SubBaseClassName> : cls_ChessPieces 
{
     public abstract bool CheckLegalMove();
}
class:cls\u棋子
{
公共摘要bool CheckLegalMove();
}

您的
cls\u典当
将继承自
,您可以检查
piece1
是否属于
类型,如果它是
CheckLegalMove
方法,则在其上调用
CheckLegalMove
方法。

对于这个答案,我想您不想在
cls\u ChessPieces
基础中有一个抽象的
CheckLegalMove
方法班级。如果这不是问题,不要选择这种方法

方法1(不推荐) 您可以使用

var type = piece1.GetType();
然后检查每个反射类型是否通过执行以下操作定义了方法
CheckLegalMove()

var type = piece1.GetType();
var checkLegalMoveMethod = type.GetMethod("CheckLegalMove");

if(checkLegalMoveMethod != null)   
{  
    var result = (bool)checkLegalMoveMethod.Invoke(piece1);  
}
这是可行的,但前提是CheckLegalMove方法不包含任何参数

方法2(推荐方法) 您还可以做的一件事是引入另一个基类(同样,仅当您不想在
cls\u ChessPieces
中直接使用CheckLegalMove方法时才这样做)
,该基类定义如下:

class <SubBaseClassName> : cls_ChessPieces 
{
     public abstract bool CheckLegalMove();
}
class:cls\u棋子
{
公共摘要bool CheckLegalMove();
}

您的
cls\u典当将继承自
,您只需检查
piece1
是否为
类型,如果为
CheckLegalMove
方法即可。
CheckLegalMove
对于每一个片段来说都是一个有效的问题,因此它的声明无论如何都应该属于抽象基类。重新编辑:在这种情况下,典型的模式仍然是使用
Promote
基类方法,在除pawn实现之外的任何实现上抛出一个
NotSupportedException
。@Cee抛出NotSupportedExceptions很少是正确的选择(您基本上是在处理静态类型系统)。对于促销,我可以根据总体选择想出几个更好的选择。一个简单的选择是让它
piecpromote()=>这个作为基类中的默认实现,并且只在pawn类中覆盖它,还有其他的可能性。我认为要解决这些问题,必须使用一些模式。例如,访问者模式可以应用于这种情况。重新思考体系结构。
CheckLegalMove
对于每一个片段来说都是一个有效的问题,因此它的声明无论如何都应该属于抽象基类。重新编辑:在这种情况下,典型的模式仍然是使用
Promote
基类方法,在除pawn实现之外的任何实现上抛出一个
NotSupportedException
。@Cee抛出NotSupportedExceptions很少是正确的选择(您基本上是在处理静态类型系统)。对于促销,我可以根据总体选择想出几个更好的选择。一个简单的选择是让它
piecpromote()=>这个作为基类中的默认实现,并且只在pawn类中覆盖它,还有其他的可能性。我认为要解决这些问题,必须使用一些模式。例如,Visitor模式可以应用于这种情况,我知道在bass类中创建CheckLegalMove()可能更好。但是,如果我创建一个方法Promote(),允许棋子升级到另一个棋子呢。这个方法应该只属于子类cls_Pawn。@jlepers,是的,我同意Promote()不应该在基类中。但也许它也不应该在当铺上。某种棋盘类应该有它,并替换棋盘上的棋子(移除棋子并创建一个新棋子)@jleppers在这种情况下使用模式匹配,例如如果(棋子1是cls_Pawn Pawn){Pawn.CheckLegalMove()}
,这更为具体