Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top