1

I'm defining two Abstract Classes: AC1, and AC2. AC1 has a property (variable) which is a List of type AC2 (List<AC2>) (that's my way of defining a 1 to many relation).

Then, I defined R1 which comes from AC1 (R1 : AC1) and R2 : AC2. The problem comes when I'm writing R1's constructor. I'm passing as a parameter a List of type R2 (List<R2>) and then try to assign it to the property (variable) defined in AC1 (List<AC2>), but this fails as it cannot implicitly convert from R2 to AC2 (even when R2 comes from AC2).

Code example:

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
    }
}

I'll have some other classes coming from this abstract classes, but each time that I create a class (X2, for example) that comes from AC2 I'll need an X1 class that has a List<X2>.

Am I failing in design or implementation?

I'll appreciate any help.

StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • Don't confuse OOP with the entity-relationship model. OOP is much closer to the network data model and doesn't support ternary and higher-order relationships, non-directed relationships, weak entities, identifying relationships or participation constraints. I suggest you use OOP for systems modeling, not for data modeling. – reaanb Aug 15 '17 at 05:56

2 Answers2

1

There's a couple issues here.

  • Firstly, you'll need to change the protection level of dammVariable to at least protected in order to access it in subclasses.

  • But then you'll be faced with a type safety problem:

CS0029: Cannot implicitly convert type System.Collections.Generic.List<R2> to System.Collections.Generic.List<AC2>

This is because List<T> is invariant, so you will not be able to assign List<R2> to List<AC2> despite the inheritance relationship between R2 and AC2.

Assuming once assigned, that you never actually need to add / remove elements from the dammVariable, change the type from List to a type which allows for covariance, e.g.

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

More on covariance / contravariance in this Question

StuartLC
  • 104,537
  • 17
  • 209
  • 285
0

First, I assume that dammVariable is protected or public, because it will fail if not.

Second, C# cannot implicitly convert from List< R2> to List< AC2>. You should assign every element of dammVariable using a for loop.

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];
            }
        }
    }
  • Thanks! But, I'd be force to give to the R1 constructor a List of abstract classes wich is not what I want. In fact I tried that, but when I try to instantiate R1 with a List< R2> (R1 r = new R1(r2s) // where r2s type is List< R2>) I get an "cannot convert from R2 to AC2" error (error code CS1503) – Oliver Mohr Bonometti Aug 15 '17 at 05:03
  • See edit please. I meant to pass a list of R2, not AC2. You cannot do the conversion from List< R2> to List< AC2> but you can assign a single R2 element to a single AC2 element – Shalon Isaac Aug 15 '17 at 05:10
  • Well, the this.dammVariable = r2s; is going to fail (it's the original problem). Assuming I have to delete that line i get an error inside the for loop wich says "object reference not set to an object instance". Note that even that dammVariable is Instantiated in the "this.dammVariable = new List< AC2>();" line it still appears with null value in the local variable debugger – Oliver Mohr Bonometti Aug 15 '17 at 05:20
  • @Jonskeet lists some more elegant ways to achieve [this hack](https://stackoverflow.com/a/4931809/314291) – StuartLC Aug 15 '17 at 05:31