Reputation: 349
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.
Upvotes: 1
Views: 860
Reputation: 20353
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
}
}
Upvotes: 4