2017-08-15 1 views
1

Je définis deux classes abstraites: AC1 et AC2. AC1 a une propriété (variable) qui est List de type AC2 (List<AC2>) (c'est ma façon de définir une relation de 1 à plusieurs).Erreur lors de l'application de la relation de l'entité avec les classes abstraites lors de l'affectation d'une liste contenant une classe plus dérivée

Ensuite, j'ai défini R1 qui vient de AC1 (R1 : AC1) et R2 : AC2. Le problème vient quand j'écris le constructeur de R1. Je passe en paramètre une liste de type R2 (List<R2>) et essaye ensuite de l'assigner à la propriété (variable) définie dans AC1 (List<AC2>), mais elle échoue car elle ne peut pas implicitement convertir de R2 en AC2 (même lorsque R2 vient de AC2).

Exemple de code:

abstract class AC2 
{ 
    //several properties and methods here 
} 

abstract class AC1 
{ 
    List<AC2> dammVariable {get; set;} //problematic variable (see class R1) 
    //other stuff here 
} 

class R2 : AC2 
{ 
    //some properties exclusive for R2 here 
    public R2(){} 
} 

class R1 : AC1 
{ 
    //some properties exclusive for R1 here 
    public R1(List<R2> r2s) 
    { 
     this.dammVariable = r2s; //I found the error right here 
    } 
} 

Je vais avoir quelques autres classes à venir de cette classes abstraites, mais chaque fois que je crée une classe (X2, par exemple) qui vient de AC2 je besoin d'un Classe X1 qui a un List<X2>.

Est-ce que j'échoue dans la conception ou la mise en œuvre?

J'apprécie toute aide.

+0

Ne confondez pas OOP avec le modèle entité-relation. La POO est beaucoup plus proche du modèle de données de réseau et ne supporte pas les relations ternaires et d'ordre supérieur, les relations non dirigées, les entités faibles, les relations d'identification ou les contraintes de participation. Je vous suggère d'utiliser la POO pour la modélisation de systèmes, pas pour la modélisation de données. – reaanb

Répondre

0

D'abord, je suppose que dammVariable est protégé ou public, car il échouera sinon.

Deuxièmement, C# ne peut pas convertir implicitement de la liste < R2> à la liste < AC2>. Vous devez affecter chaque élément de dammVariable en utilisant une boucle for.

class R1 : AC1 
    { 
     public R1(List<R2> r2s) 
     { 
      this.dammVariable = r2s; 
      this.dammVariable= new List<AC2>(); 
      for(int i = 0; i<r2s.Count; i++) 
      { 
       this.dammVariable[i] = r2s[i]; 
      } 
     } 
    } 
+0

Merci! Mais, je serais obligé de donner au constructeur R1 une liste de classes abstraites qui n'est pas ce que je veux. En fait j'ai essayé cela, mais quand j'essaye d'instancier R1 avec une liste < R2> (R1 r = nouveau R1 (r2s) // où le type de r2s est la liste < R2>) j'obtiens une erreur «ne peut pas convertir de R2 en AC2» (code d'erreur CS1503) –

+0

Voir modification s'il vous plaît. Je voulais passer une liste de R2, pas AC2. Vous ne pouvez pas effectuer la conversion de la liste < R2> vers la liste < AC2> mais vous pouvez affecter un seul élément R2 à un seul élément AC2. –

+0

Eh bien, this.dammVariable = r2s; va échouer (c'est le problème original). En supposant que je doive supprimer cette ligne, j'obtiens une erreur dans la boucle for qui indique "la référence d'objet n'est pas définie sur une instance d'objet". Notez que même ce dammVariable est instancié dans le "this.dammVariable = new List < AC2>();" ligne il apparaît toujours avec une valeur nulle dans le débogueur de variable locale –

1

Il y a quelques problèmes ici.

  • Tout d'abord, vous aurez besoin de changer le niveau de protection de dammVariable au moins protected afin d'y accéder dans les sous-classes.

  • Mais alors vous serez confrontés à un problème de sécurité de type:

CS0029: ne peut pas convertir implicitement le type System.Collections.Generic.List<R2> à System.Collections.Generic.List<AC2>

C'est parce que List<T> est invariant, donc vous ne serez pas en mesure d'affecter List<R2> à List<AC2> malgré la relation d'héritage entre R2 et AC2.

En supposant qu'une fois affecté, que vous n'avez jamais réellement besoin d'ajouter/supprimer des éléments du dammVariable, changez le type de Liste en un type qui permet la covariance, par ex.

abstract class AC1 
{ 
    protected IEnumerable<AC2> dammVariable {get; set;} 
) 

Plus sur covariance/contravariance dans this Question

+0

A travaillé comme charme! Je vous remercie. –