我有一个基础对象列表(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设计方式是不合适的。
答案 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对象。