构造函数中的基础对象作为向下转换的替代方法

时间:2009-07-29 09:19:30

标签: c# oop downcast

我有一个基础对象列表(RTUDevice),并希望迭代并将每个对象转换为派生对象(实际上是派生的RTDSensor),但是向下转换会抛出错误。

public RTUDevice(int id)
{
    _id = id;
}

public class RTDDevice : RTUDevice
{
    public RTDDevice(int id)
        : base(id)
    {

    }
}

public class RTDSensor : RTDDevice
{
    public RTDSensor(int id)
        : base(id)
    {

    }
}

RTDSensor return = (RTDSensor)_devices.Find(d => d.Id == p.ReturnId);

将构造函数中的基础对象传递给RTDSensor(如

)会更好吗?
public RTDSensor(RTUDevice rtu) : base(rtu.Id)
{
}

或者我的OOP设计方式是不合适的。

2 个答案:

答案 0 :(得分:1)

我认为这与构造函数调用没有任何关系 - 问题是你试图将一种类型的对象转换为另一种类型。除非您涉及用户定义的转换(如果涉及的两种类型属于同一继承层次结构,则无法进行转换),从不调用构造函数。

如果您想创建更多派生类型的 new 对象,请继续:

RTUDevice device = _devices.Find(d => d.Id == p.ReturnId);
RTDSensor sensor = new RTDSensor(device); // Or whatever

如果您要转换所有对象,这是List<RTUDevice>,那么您可以使用:

List<RTDSensor> sensors = _devices.ConvertAll(device => new RTDSensor(device));

或更基于LINQ的方法:

IEnumerable<RTDSensor> x = _devices.Select(device => new RTDSensor(device));

...但你不能只告诉.NET将对象视为比实际更具体的类型。要把它变得荒谬,你期望这样做:

object o = new object();
FileStream fs = (FileStream) o;
rs.ReadByte(); // Where from?

编辑:我认为你不能改变_devices集合中的内容。如果你可以确保它包含适当类型的对象,那么这很好 - 如果没有,你需要稍后创建新对象。

答案 1 :(得分:1)

问题可能在于您将设备添加到_devices集合的方式。

例如:

RTDSensor sensor = new RTDSensor(1);
_devices.Add(sensor);
RTDSensor retrievedSensor = (RTDSensor)_devices.Find(d => d.Id == 1);

应该有效。但是,如果将传感器添加为RTUDevice对象,则之后无法将其转换为RTDSensor,因为它没有RTDSensor携带的其他信息。

参考Jon Skeet的例子,你必须使用

object o = new FileStream(path, filemode);
FileStream fs = (FileStream)o;

如果您以后想要将o转换为FileStream对象。