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

时间:2016-09-15 11:44:58

标签: c# inheritance

我正在为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

现在,在MyPlateFloor类的代码中,我需要使用Plate modelObject来访问它的方法。目前,我通过向下转发modelObject

来实现这一目标
(modelObject as Plate).doSomething;

这种方法有用,但我想让它变得更简单。然而,主要的问题是,当我尝试访问modelObject的成员时,我无法将它们作为参考。例如,当我尝试声明points时,它不会引用modelObject.points

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

有没有办法将变量声明为对modelObject的引用,以便可以对它们进行操作?

3 个答案:

答案 0 :(得分:2)

这实际上是两个问题。部分,为什么你的积分不会被删除已经得到了回答。但为了完整起见,这里有摘要:

删除参考

当您致电var points = (modelObject as Plate).points时,您复制对points modelObject对象的引用。使用points = null,您只需删除(null)对points的{​​{1}}的引用,但modelObject仍会保留对modelObject的引用。

要删除pointsmodelObject的引用,请致电points

在子类中进行向下转换

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

方法隐藏

Methhides方法或基类的另一个成员,并为名称提供新的含义。这样,您可以为子类成员赋予另一种含义和另一种返回类型。要实现此目的,您应该将modelObject封装在Property中。你的代码是这样的:

(modelObject as Plate).points = null

注意,在子类中使用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 { ... } 。这使您仍然可以访问基类ModelObject,尽管您已经为ModelObject赋予了新的含义。除了方法重写之外,您保留基类Member,并仅提供具有相同名称的另一含义。

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

base.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. } } )对Plate的类型进行参数化。这稍微复杂一些,但也更简洁,因为子类化和转换没有像方法隐藏这样的混乱效果。

TPlate

以上示例不允许MyFloor进一步专门化Type参数,但这也可以实现:

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
{
    ...
}

答案 1 :(得分:1)

您正在创建参考的副本。 points = (modelObject as Plate).points;所以points(modelObject as Plate).points指向相同的记忆。将null分配给points时,会清除一个引用。另一个仍然存在。

如果您希望(modelObject as Plate).points;为空。只需使用:(modelObject as Plate).points = null;

这与投射没有任何关系。

答案 2 :(得分:0)

当您将points设置为null时,您将取消名为&#34;&#34;的引用。在范围内,而不是实际变量。如果你真的不想做modelObject.points = null(你通常只是这样做),你想通过参考来实际操作它。

请参阅https://msdn.microsoft.com/en-us/library/14akc2c7.aspx

那就是说,我不确定为什么你要对这些物品进行低估,因为我们无法在这里看到足够的事情来确定这些物体。