构造函数中的基对象作为向下转型的替代方案

发布于 2024-07-29 00:06:55 字数 575 浏览 6 评论 0原文

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

I have a list of base objects (RTUDevice) and want to iterate through and convert each to a derived object (actually a derived of a derived RTDSensor) , however the downcasting is throwing an error.

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);

Would it be better to pass the base object in a constructor to RTDSensor like

public RTDSensor(RTUDevice rtu) : base(rtu.Id)
{
}

or is my OOP design way off the mark.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青巷忧颜 2024-08-05 00:06:55

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

例如:

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

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

必须使用。

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

参考 Jon Skeet 的示例,如果您稍后想要将 o 转换为 FileStream 对象,则

The problem could be with the way you're adding the devices to the _devices collection.

For example:

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

should work. However if you add the sensor as an RTUDevice object you can't cast it to RTDSensor afterwards because it doesn't have the additional information that RTDSensor carries.

Referring to Jon Skeet's example you have to use

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

If you later want to cast o to a FileStream object.

惜醉颜 2024-08-05 00:06:55

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

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

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

如果您想转换所有对象,并且这是一个List,那么您可以使用:

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

I don't think this really has anything to do with the constructor call - the problem is you're trying to cast an object of one type to another. That never calls a constructor, unless you've got a user-defined conversion involved (which you can't if the two types involved are in the same inheritance hierarchy.)

If you want to create a new object of the more derived type, go ahead:

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

If you want to convert all the objects, and this is a List<RTUDevice> then you could use:

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

or the more LINQ-based approach:

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

... but you can't just tell .NET to treat an object as if it were a more specific type than it actually is. To take it to a ridiculous length, what would you expect this to do:

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

EDIT: I've assumed that you can't change what's in the _devices collection. If you can make sure that it contains objects of the appropriate type to start with, that's great - if not, you'll need to create the new objects later.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文