web-dev-qa-db-fra.com

Conversion de la classe de base en classe dérivée

Est-il possible en C # de convertir explicitement un objet de classe de base en une de ses classes dérivées? Je pense actuellement que je dois créer un constructeur pour mes classes dérivées qui accepte un objet de classe de base en tant que paramètre et copie les valeurs de propriété. Je n'aime pas vraiment cette idée, alors j'aimerais bien l'éviter si possible.

Cela ne semble pas fonctionner normalement (l'objet est instancié en tant que nouvelle base, la mémoire ne doit donc pas être allouée à des membres supplémentaires de la classe dérivée), mais C # semble me permettre de le faire:

class BaseClass
{
  ... some stuff ...
}

class DerivedClass : BaseClass
{
    public bool MyDerivedProperty{ get; set; }
}


static void Main(string[] args)
{
    BaseClass myBaseObject = new BaseClass();
    DerivedClass myDerivedObject = myBaseObject as DerivedClass;

    myDerivedObject.MyDerivedProperty = true;
}
104
ARW

Non, il n'y a pas de moyen intégré pour convertir une classe comme vous le dites. Le moyen le plus simple de procéder consiste à faire ce que vous avez suggéré: créer un constructeur DerivedClass(BaseClass). D’autres options permettraient essentiellement d’automatiser la copie des propriétés de la base vers l’instance dérivée, par exemple. en utilisant la réflexion.

Le code que vous avez publié à l'aide de as sera compilé, comme vous l'avez sans doute déjà vu, mais émettra une exception de référence null lorsque vous l'exécuterez, car myBaseObject as DerivedClass sera évalué à null, puisque ce n'est pas une instance de DerivedClass.

86
Tim S.

Ce n'est pas possible. mais vous pouvez utiliser un mappeur d'objets comme AutoMapper

Exemple:

class A
{
    public int IntProp { get; set; }
}
class B
{
    public int IntProp { get; set; }
    public string StrProp { get; set; }
}

Dans global.asax ou au démarrage de l'application:

AutoMapper.Mapper.CreateMap<A, B>();

Usage:

var b = AutoMapper.Mapper.Map<B>(a);

Il est facilement configurable via une API fluide.

49
Mahmoodvcs

J'ai trouvé une solution à cela, sans dire que c'est la meilleure, mais elle me semble propre et ne nécessite aucune modification majeure de mon code. Mon code ressemblait au vôtre jusqu'à ce que je réalise que cela ne fonctionnait pas.

Ma classe de base

public class MyBaseClass
{
   public string BaseProperty1 { get; set; }
   public string BaseProperty2 { get; set; }
   public string BaseProperty3 { get; set; }
   public string BaseProperty4 { get; set; }
   public string BaseProperty5 { get; set; }
}

Ma classe dérivée

public class MyDerivedClass : MyBaseClass
{
   public string DerivedProperty1 { get; set; }
   public string DerivedProperty2 { get; set; }
   public string DerivedProperty3 { get; set; }
}

Méthode précédente pour obtenir une classe de base renseignée

public MyBaseClass GetPopulatedBaseClass()
{
   var myBaseClass = new MyBaseClass();

   myBaseClass.BaseProperty1 = "Something"
   myBaseClass.BaseProperty2 = "Something else"
   myBaseClass.BaseProperty3 = "Something more"
   //etc...

   return myBaseClass;
}

Avant, j'essayais cela, ce qui m'avait empêché de lancer une erreur

public MyDerivedClass GetPopulatedDerivedClass()
{
   var newDerivedClass = (MyDerivedClass)GetPopulatedBaseClass();

   newDerivedClass.UniqueProperty1 = "Some One";
   newDerivedClass.UniqueProperty2 = "Some Thing";
   newDerivedClass.UniqueProperty3 = "Some Thing Else";

   return newDerivedClass;
}

J'ai changé mon code comme suit ci-dessous et cela semble fonctionner et a plus de sens maintenant:

ancien

public MyBaseClass GetPopulatedBaseClass()
{
   var myBaseClass = new MyBaseClass();

   myBaseClass.BaseProperty1 = "Something"
   myBaseClass.BaseProperty2 = "Something else"
   myBaseClass.BaseProperty3 = "Something more"
   //etc...

   return myBaseClass;
}

Nouvea

public void FillBaseClass(MyBaseClass myBaseClass)
{
   myBaseClass.BaseProperty1 = "Something"
   myBaseClass.BaseProperty2 = "Something else"
   myBaseClass.BaseProperty3 = "Something more"
   //etc...
}

ancien

public MyDerivedClass GetPopulatedDerivedClass()
{
   var newDerivedClass = (MyDerivedClass)GetPopulatedBaseClass();

   newDerivedClass.UniqueProperty1 = "Some One";
   newDerivedClass.UniqueProperty2 = "Some Thing";
   newDerivedClass.UniqueProperty3 = "Some Thing Else";

   return newDerivedClass;
}

Nouvea

public MyDerivedClass GetPopulatedDerivedClass()
{
   var newDerivedClass = new MyDerivedClass();

   FillBaseClass(newDerivedClass);

   newDerivedClass.UniqueProperty1 = "Some One";
   newDerivedClass.UniqueProperty2 = "Some Thing";
   newDerivedClass.UniqueProperty3 = "Some Thing Else";

   return newDerivedClass;
}
9
meffect

Vous pouvez implémenter la conversion vous-même, mais je ne le recommanderais pas. Jetez un coup d'oeil au motif de décorateur si vous voulez le faire afin d'étendre les fonctionnalités d'un objet existant.

6
Matthias Meid

Non, il n'y a pas de conversion intégrée pour cela. Vous devrez créer un constructeur, comme vous l'avez mentionné, ou une autre méthode de conversion.

De plus, puisque BaseClass n'est pas une DerivedClass, myDerivedObject sera null et la dernière ligne ci-dessus lève une exception null ref.

1
Erix

Non ce n'est pas possible. La seule façon possible est

static void Main(string[] args)
{
    BaseClass myBaseObject = new DerivedClass();
    DerivedClass myDerivedObject = myBaseObject as DerivedClass;

    myDerivedObject.MyDerivedProperty = true;
}
1
Jan P.