C# 向下转换继承类中基类中声明的对象

C# 向下转换继承类中基类中声明的对象,c#,inheritance,C#,Inheritance,我正在为API创建一个插件,但在继承方面有问题。有没有一种方法可以在继承自基类的类中“自动”向下转换在基类中声明的对象 我的班级结构如下: abstract class MyPart { public Part modelObject; ... } class MyPlate : MyPart { public ArraList points; // from API ... } class Floor : MyPlate { ... } Part是

我正在为API创建一个插件,但在继承方面有问题。有没有一种方法可以在继承自基类的类中“自动”向下转换在基类中声明的对象

我的班级结构如下:

abstract class MyPart
{
    public Part modelObject;
    ...
}

class MyPlate : MyPart
{
    public ArraList points; // from API
    ...
}

class Floor : MyPlate
{
    ...
}
Part
是一个API类,其类结构如下所示:

class Part
class Plate : Part
现在,在
MyPlate
Floor
类中的代码中,我需要使用
Plate modelObject
来访问它的方法。目前,我通过向下转换
modelObject
来实现这一点:

(modelObject as Plate).doSomething;
虽然我想让它更简单一些,但这种方法还是有效的。然而,主要的问题是,当我试图访问
modelObject
的成员时,我无法将它们作为引用。例如,当我试图声明
点时,它不引用
模型对象。点

points = (modelObject as Plate).points;
points = null; // modelObject.points != null

有没有一种方法可以将变量声明为对
modelObject
的引用,以便对其进行操作?

当您将
点设置为
null
时,您将清空范围中名为“points”的引用,而不是实际的变量。如果您真的不想只做
modelObject.points=null
(您通常只做),您希望通过ref操作它来实际访问它


也就是说,我不知道为什么要向下转换对象,因为我们看不到足够的信息来确定这一点。

当您将
点设置为
null
时,您将清空范围中名为“points”的引用,而不是实际变量。如果您真的不想只做
modelObject.points=null
(您通常只做),您希望通过ref操作它来实际访问它


也就是说,我不确定您为什么要向下投射这些对象,因为我们看不到足够的情况来确定这一点。

您正在创建引用的副本<代码>点=(模型对象为图版)。点
So
(模型对象为图版)。点
指向相同的内存。当您将
null
分配给
点时,一个参考被清除。另一个仍然存在

如果您想要
(模型对象为图版)。点设置为空。只需使用:
(modelObject作为模板)。points=null


这与铸造没有任何关系。

您正在创建参考文件的副本<代码>点=(模型对象为图版)。点
So
(模型对象为图版)。点
指向相同的内存。当您将
null
分配给
点时,一个参考被清除。另一个仍然存在

如果您想要
(模型对象为图版)。点设置为空。只需使用:
(modelObject作为模板)。points=null


这与铸造没有任何关系。

这实际上是两个问题。关于为什么你的观点不会被删除的部分已经回答了。但为了完整起见,这里是总结:

删除引用 调用
var points=(modelObject为图版).points
时,将引用复制到
modelObject
points
对象。使用
points=null
只需删除(null)对
modelObject
点的引用,但
modelObject
仍保留对
点的引用

要删除
modelObject
点的引用,请调用
(modelObject为图版)。points=null

子类中的向下投射 但是对于您的主要问题,如何自动向下转换子类中的对象。有两种方法可以实现这一点。方法隐藏和泛型:

方法隐藏

Meth隐藏基类的方法或其他成员,并为名称提供新的含义。这样,就可以给子类成员另一个含义和另一个返回类型。要实现这一点,您应该将modelObject封装在属性中。您的代码如下所示:

abstract class MyPart
{
    private Part modelObject;
    public Part ModelObject 
    {
       get { return modelObject; }
       set { modelObject = value; }
    }
    ...
}

class MyPlate : MyPart
{
    public new Plate ModelObject 
    {
        get { return base.ModelObject as Plate; }
        set { base.ModelObject = value; }
    public ArraList points; // from API
    ...
}

class Floor : MyPlate
{
    ...
}
注意,在子类中使用
base.ModelObject
。这使您仍然可以访问基类ModelObject,尽管您给ModelObject赋予了新的含义。除了方法重写之外,您保留基类成员,并且只提供具有相同名称的另一个含义

注意,这有一些含义。最重要的一点是,类不知道成员是否隐藏在子类中,这意味着转换到基类的子类将始终运行基类功能。请参见以下代码示例以进行说明

public class Base 
{
    public void Do() 
    {
        Console.WriteLine("Base");
    }
}
public class Sub : Base
{
    public new void Do() 
    {
        Console.WriteLine("Sub");
    }
}
public class Program 
{
    public static void Main(string[] args) 
    {
        Sub sub = new Sub();
        Base base = sub;

        sub.Do(); //prints Sub
        base.Do(); //prints Base, even though it is the same object.
    }
}
仿制药

另一方面,使用泛型,您可以使用类型参数(示例中为
TPlate
)对板材类型进行参数化。这稍微复杂一点,但也是更干净的方法,因为子类化和强制转换没有像方法隐藏这样令人困惑的效果

abstract class MyPart<TPart> 
    where TPart : Part //configure a type parameter
{
    public TPart modelObject;
    ...
}

class MyPlate : MyPart<Plate> //TPlate is now of type Plate
{
    public ArraList points; // from API
    ...
}

class Floor : MyPlate
{
    ...
}
抽象类MyPart
其中TPart:Part//配置类型参数
{
公共TPart模型对象;
...
}
MyPlate类:MyPart//TPlate现在是Plate类型
{
公共列表点;//来自API
...
}
班级楼层:MyPlate
{
...
}
上面的示例不允许MyFloor进一步专门化类型参数,但这也可以实现:

abstract class MyPart<TPart> 
    where TPart : Part //configure a type parameter and force it to be a subclass of Part
{
    public TPart modelObject;
    ...
}

class MyPlate<TPlate> : MyPart<TPlate> 
    where TPlate : Plate //force the type parameter to be a subclass of Plate
{
    public ArraList points; // from API
    ...
}

class Floor : MyPlate<Floor> //TType is now Floor
{
    ...
}
抽象类MyPart
其中TPart:Part//配置一个类型参数,并强制它成为Part的子类
{
公共TPart模型对象;
...
}
类别MyPlate:MyPart
其中TPlate:Plate//强制类型参数为Plate的子类
{
公共列表点;//来自API
...
}
班级楼层:MyPlate//t类型现在为楼层
{
...
}

这实际上是两个问题。关于为什么你的观点不会被删除的部分已经回答了。但为了完整起见,这里是总结:

德尔