C# 中的运行时类型转换

Runtime TypeCasting in C#

IDE: VS2010, C# .NET 4.0

我想知道是否有任何方法可以按照传入变量的方式对对象进行类型转换,例如:

#CODE BLOCK 1  
    private void ReArrangeShapeLocation(Shape currentControl, double scalePrecentageHeight, double scalePrecentageWidth)
    {
        //here I need to type cast control according to their type

        //example code
        int cX = (currentControl as RectangleShape).Location.X;
        int cXo = (currentControl as OvalShape).Location.X;  
        //Computation code.
    }  

此处形状 class 在 c# 命名空间

中可用
Microsoft.VisualBasic.PowerPacks  

RectangleShape 和 OvalShape 是 Shape class 的子 classes。

所以在上面的代码中,如果我通过

ReArrangeShapeLocation(somRectrangleShape1,14,34);
ReArrangeShapeLocation(somOvelShape1,15,15);  

因为这里我在同一个函数中传递矩形和椭圆形以获得它们在函数中的位置(参见代码块#1),我需要相应地类型转换 Shape 对象。

无论我在 ReArrangeShapeLocation 函数中传递什么,c# 中是否有任何方法可以根据子 class 对形状对象进行类型转换。

#CODE BLOCK 1  
    private void ReArrangeShapeLocationDYNAMIC(Shape currentControl, double scalePrecentageHeight, double scalePrecentageWidth)
    {
        //here I need to type cast control according to their type

        //example code
        int cX = (currentControl as Typeof(currentControl)).Location.X;

    }      

我知道可以使用我不想要的 switch case 来完成。我也知道在 c# 中这可能是使用 Reflaction 完成的,但我不知道。

这其实没有必要,恰恰是多态的重点。从 Shape 派生的任何 class 都将具有在 Shape 中声明的相应属性。因此,要获得坐标(我假设它是 Shape class 的一部分),传递给方法的形状无关紧要。

可以 将基础对象转换为专用对象,但前提是您确定您获得的对象具有正确的类型。

例如这个有效:

Shape r = new RectangleShape();
RectangleShape r1 = r as RectangleShape();

虽然这不是:

Shape p = new PolygonShape();
RectangleShape p1 = p as RectangleShape();

我注意到 Shape class 没有定义坐标,但是 SimpleShape class 定义了坐标,这是从 Shape 派生的。当您依赖代码中的 Location 属性 时,您需要确保获得的 ShapeSimpleShape.

您可以将方法声明更改为采用 SimpleShape 参数:

private void ReArrangeShapeLocation(SimpleShape currentControl, double scalePrecentageHeight, double scalePrecentageWidth)
{
    int cX = currentControl.Location.X;
}  

或者你可以保持原样,如果传递错误则抛出异常:

private void ReArrangeShapeLocation(Shape currentControl, double scalePrecentageHeight, double scalePrecentageWidth)
{
    if (!(currentControl is SimpleShape))
        throw new ArgumentException("currentControl is not a SimpleShape");

    int cX = (currentControl as SimpleShape).Location.X;
}  

或者您也可以扩展您的方法来处理 LineShape

private void ReArrangeShapeLocation(Shape currentControl, double scalePrecentageHeight, double scalePrecentageWidth)
{
    int cX = 0;

    if (currentControl is SimpleShape)
    {
        cX = (currentControl as SimpleShape).Location.X;
    }
    else if (currentControl is LineShape)
    {
        cX = (currentControl as LineShape).X1;
    }
}  

通过查看 Shape MSDN 页面,Shape 似乎没有 Location 属性...您仍然可以使用 dynamic:

dynamic currentControl2 = currentControl;
int cx = currentControl2.Location.X;

请注意,在这种特定情况下,还有另一种更好的可能性,如 Thorsten Dittmar 所写:使用 SimpleShape.

请改用 SimpleShape class。这是具有 Location 属性:

的继承对象
private void ReArrangeShapeLocationDYNAMIC(SimpleShape currentControl, 
    double scalePrecentageHeight, double scalePrecentageWidth)
{
    int cX = currentControl.Location.X;

}