2

我有一个基础对象列表 (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 设计偏离了标准。

4

2 回答 2

1

我认为这与构造函数调用没有任何关系 - 问题是您试图将一种类型的对象转换为另一种类型。这永远不会调用构造函数,除非您涉及用户定义的转换(如果所涉及的两种类型位于同一继承层次结构中,则不能这样做。)

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

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集合中的内容。如果您可以确保它包含适当类型的对象,那就太好了 - 如果没有,您将需要稍后创建新对象。

于 2009-07-29T09:24:27.843 回答
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 对象。

于 2009-07-29T09:33:55.747 回答