简体   繁体   中英

Cannot add a derived class object to a list of it's base class type

I have the following class structure:

//BaseClass
public abstract class BaseClass<T> where T : Model
{
    public abstract T Data { get; set; }
    public BaseClass(T data) { Data = data; }
}

public abstract class Model
{
    public int Id { get; set; }
}

//ClassA
public class BaseClassA : BaseClass<ModelA>
{
    public override ModelA Data { get; set; }
    public BaseClassA(ModelA data) : base(data) { }
}

public class ModelA : Model { }

//ClassB
public class BaseClassB : BaseClass<ModelB>
{
    public override ModelB Data { get; set; }
    public BaseClassB(ModelB data) : base(data) { }
}

public class ModelB : Model { }

I would like to use them as follows:

List<BaseClass<Model>> myBaseList = new List<BaseClass<Model>>();
myBaseList.Add(new BaseClassA(new ModelA()));
myBaseList.Add(new BaseClassB(new ModelB()));

foreach (var item in myBaseList)
{
    if (item.Data.Id > 0)
    {
        //do stuff
    }
}

But I get the compiler exception:

cannot convert from BaseClassA to BaseClass<Model>

However, I was under the impresion that BaseClassA being of type BaseClass<ModelA> would be meet the requirement of being of type BaseClass<Model>.

For instance, this doesn't generate any errors:

List<Model> myModelList = new List<Model>();
myModelList.Add(new ModelA());
myModelList.Add(new ModelB());

I can't seem to wrap my head around where I went wrong with this.

One possible solution would be to introduce a covariant interface:

public interface IBase<out T> where T : Model
{
    T Data { get; }
}

public abstract class BaseClass<T> : IBase<T> where T : Model

Then use the interface for your list:

var myBaseList = new List<IBase<Model>>();
myBaseList.Add(new BaseClassA(new ModelA()));
myBaseList.Add(new BaseClassB(new ModelB()));

Because IBase declares Data as get-only, this ensures type-safety.

And here you still have access to Data :

foreach (var item in myBaseList)
{
    if (item.Data.Id > 0)
    {
        //do stuff
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM