2010-10-29 15 views
5

Si:coulée permanente à une superclasse

class Car : Automobile 
{} 

je peux faire:

Car toyota = new Car(); 
Automobile tauto = (Automobile)toyota; 

mais si je le fais tauto.GetType().Name il sera toujours Car.

Est-il possible d'effectuer un cast, de sorte que le type est définitivement changé en Automobile (sans avoir à cloner l'objet)? Le problème que j'essaye de surmonter est qu'il n'y a aucun héritage multiple dans C#, et je dois fusionner des objets (avec la même signature) de 2 services, dans une méthode, et retourner un type.

+1

Juste curieux: pourquoi voudriez-vous faire cela? –

+1

Désolé de demander mais pourquoi voudriez-vous faire cela? L'objet ** est ** une voiture, pas une automobile. Si vous voulez une automobile, instanciez-en une. – Lazarus

+0

longue histoire, mais elle implique Entity Framework, POCOs, et son incapacité à utiliser la même classe POCO à être retourné par 2 ensembles d'entités différentes. Donc je dois contourner cela par héritage. Mais à l'extérieur, je voudrais que l'objet des deux vues soit le même .. donc il suffit de retourner la super classe. la diffusion simple est problématique car des choses comme le sérialiseur WCF et les génériques .net 3.5 traitent toujours l'objet cast comme sous-classe –

Répondre

11

Non. Il n'y a aucun moyen de le faire sans la construction d'un objet nouvel Automobile.

Cependant, il n'y a également aucune raison de le faire. Le Liskov substitution principle dit que tout Car devrait, toujours, être traitable exactement comme un Automobile, et l'utilisateur ne devrait avoir aucun changement dans le comportement attendu.

Tant que vous concevez votre hiérarchie de classes correctement, l'utilisation de Car comme Automobile devrait toujours être parfaitement acceptable.


Sur une note latérale: Cela fait partie des raisons pour lesquelles l'utilisation Type.GetType() n'est pas le meilleur moyen de vérifier le type. Il est beaucoup plus sûr, et mieux, d'utiliser les mots-clés is et as en C#. Ils retourneront vrai si vous vérifiez que tauto is Car.

+1

malheureusement wcf serializer se soucie, et 3,5 génériques se soucie aussi .. donc je ne peux pas simplement changer ce code .. je sais que je pourrais fournir ma propre sérialisation, mais il me donne beaucoup de maux de tête partout –

+0

3.5 génériques ne se soucient pas - accordée, il y a quelques problèmes potentiels avec la sérialisation WCF, mais c'est rare, et vous devrait rendre votre classe sérialisable de toute façon. Si vous avez vraiment besoin d'en faire une sous-classe, vous devrez construire un nouvel objet. Il suffit de faire un nouveau constructeur sur Automobile qui est comme ceci: 'Public Automobile (Automobile other)', et ensuite vous pouvez créer cela en passant à une routine qui se soucie vraiment ... –

0

Selon MSDN, vous êtes juste la référence à l'objet, et non l'objet sous-jacent.

0

Votre question et ce que vous essayez de faire semblent être deux choses différentes. Non, vous ne pouvez pas modifier le type sous-jacent d'un objet. Mais ce que vous semblez vouloir faire, c'est créer un type d'automobile avec un ensemble de propriétés et ne pas utiliser réellement la sous-classe. Ce que vous pouvez faire est d'utiliser une usine automobile à la place.

public static class AutomobileFactory() 
{ 
    public static Automobile CreateAutomobile(AutomobileType type) 
    { 
    ... 
    } 
} 

Où AutomobileType est une énumération. Pour plus d'informations google C# modèle d'usine.

0

Je ne sais pas exactement ce que vous essayez de faire, mais peut-être que vous pourriez envisager une approche différente? Au lieu d'essayer de fusionner la fonctionnalité de deux classes différentes en utilisant l'héritage, peut-être pourriez-vous utiliser la composition?

http://tiedyedfreaks.org/eric/CompositionVsInheritance.html

public class Service 
{ 
    public virtual void DoSomething() 
    { 

    } 
} 

public class ServiceA : Service 
{ 
    public override void DoSomething() 
    { 

    } 
} 

public class ServiceB : Service 
{ 
    public override void DoSomething() 
    { 

    } 
} 

public class ServiceA_B : Service 
{ 
    ServiceA serviceA = new ServiceA(); 
    ServiceB serviceB = new ServiceB(); 

    public override void DoSomething() 
    { 
     serviceA.DoSomething(); 
     serviceB.DoSomething(); 
    } 
} 
0

Dans certains cas, les médicaments génériques peuvent aider. Si une méthode inclut un paramètre générique, le type générique sera évalué comme le type déclaré de la référence transmise, plutôt que comme le type de l'objet transmis. Par exemple:

 
void Foo(T bar) 

Si foo() est appelée avec (Control) someButton, le type de 'bar' sera Button, mais le type de T sera le contrôle.