2009-07-29 8 views
2

J'ai une liste d'objets de base (RTUDevice) et je veux parcourir et convertir chacun en un objet dérivé (en fait un dérivé d'un RTDSensor dérivé), mais la descente est une erreur .Objet de base dans le constructeur comme alternative au downcast

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

Serait-il préférable de passer l'objet de base dans un constructeur à RTDSensor comme

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

ou est ma conception OOP fourvoyés.

+0

Y a-t-il un ORM impliqué (semble-t-il)? Que fait la méthode Find? Quelle est l'exception lancée? Etes-vous sûr que votre p.ReturnId est un RTDSensor? – Mac

Répondre

1

Le problème peut provenir de la manière dont vous ajoutez les périphériques à la collection _devices.

Par exemple:

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

devrait fonctionner. Toutefois, si vous ajoutez le capteur en tant qu'objet RTUDevice, vous ne pouvez pas le transmettre ultérieurement à RTDSensor, car il ne dispose pas des informations supplémentaires transmises par RTDSensor.

En se référant à l'exemple de Jon Skeet vous devez utiliser

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

Si vous voulez plus tard jeter o à un objet FileStream.

+0

Cela voudrait-il dire que la collection _devices est une liste de types de base et que j'y ajoute des types dérivés? –

+0

C'est une approche très courante pour stocker une collection d'objets avec un type de base commun. Cependant, si vous voulez utiliser les méthodes RTDSensor sur tous vos objets de la collection, il est bien sûr préférable de simplement en faire une collection de type RTDSensor au lieu de la lancer à chaque fois. – chrischu

+0

Cela fonctionne, merci. Les éléments proviennent d'une base de données et je voulais obtenir les informations de base dans la liste de base que je peux maintenant faire. –

1

Je ne pense pas que cela ait vraiment quelque chose à voir avec l'appel du constructeur - le problème est que vous essayez de transformer un objet d'un type en un autre. Cela n'appelle jamais un constructeur, sauf si vous avez une conversion définie par l'utilisateur (que vous ne pouvez pas faire si les deux types impliqués sont dans la même hiérarchie d'héritage.)

Si vous souhaitez créer un nouvel objet du type plus dérivé, allez-y:

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

Si vous voulez convertir tous les objets, ce qui est un List<RTUDevice> alors vous pouvez utiliser:

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

ou plus approche fondée LINQ:

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

... mais vous ne pouvez pas dire .NET pour traiter un objet comme si elle était un type plus spécifique qu'il est en réalité. Pour-il à une longueur ridicule, qu'est-ce que vous attendez ce faire:

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

EDIT: Je suis supposé que vous ne pouvez pas changer ce qui est dans la collection _devices. Si vous pouvez vous assurer qu'il contient des objets du type approprié pour commencer, c'est génial - sinon, vous devrez créer les nouveaux objets plus tard.

+0

Je pense que vous avez manqué le point d'ajouter juste le bon type d'objet à la collection ce qui serait beaucoup plus simple que de passer dans l'objet "base" au constructeur de l'objet "derived". – chrischu

+0

Vous supposez qu'il peut changer la façon dont la collection est construite. J'essaie de répondre à ce que je soupçonne être un malentendu plus fondamental: le PO pense que le cast créera un nouvel objet en appelant le constructeur. –

+0

Donne du sens à propos de la conversion. Je vais utiliser un nouvel objet et passer l'objet de base dans le constructeur. –

Questions connexes