I want to downcast interface IEntity<TM, TV, TP>
to IEntity<IModel, IView, IPresenter>
, but it gives me Invalid Cast Exception. I added some constraints (where), but it also didn't help.
Note: Im not entirely sure what is this will do, upcast or downcast in my situation
Better to show example in I try to use.
// Simple class, doesnt inherits anything.
// This class can't be generic
public class EntitiesContainer
{
private List<IEntity<IModel, IView, IPresenter>> _entities = new ();
// Adds IEntity<TM, TV, TC> to list of entities;
public void Add<TM, TV, TC>(IEntity<TM, TV, TC> entity)
where TM : IModel
where TV : IView
where TC : IPresenter
{
_entities.Add((IEntity<IModel, IView, IPresenter>)entity); // invalid cast
//or it says: argument type IEntity<TM, TV, TC> is not assignable to IEntity
//_entities.Add(entity); //syntax error
}
// some other methods below...
}
IEntity:
public interface IEntity<TM, TV, TP>
where TM : IModel
where TV : IView
where TP : IPresenter
{
TM Model { get; }
TV View { get; }
TP Presenter { get; }
}
This example I want to add IEntity to list. Class has a List of IEntity<IModel, IView, IPresenter>
, but it is a problem to add IEntity
with generic parameters. E.g. IEntity<ImplModel, ImplView, ImplPresenter
, because it can't be downcasted/upcasted to <IEntity<IModel, IView, IPresenter>>
ImplModel, ImplView, ImplPresenter- they all Implements its interfaces respectively (IModel, IView, IPresenter)
I did some research. Looks like I need to use something called generics covariance. By documentation, I need to put in or out in class. But I have List of specific generics and in or out will not help.
Any help will be helpfull. Thanks.
CodePudding user response:
You can add out
specifier into your IEntity
interface declaration and then remove cast completely
class TestModel:IModel{}
class TestView:IView{}
class TestPresenter:IPresenter{}
class TestEntity : IEntity<TestModel, TestView, TestPresenter>{}
// Simple class, doesnt inherits anything.
// This class can't be generic
public class EntitiesContainer
{
private List<IEntity<IModel, IView, IPresenter>> _entities = new ();
public void Test() => Add(new TestEntity());
// Adds IEntity<TM, TV, TC> to list of entities;
public void Add(IEntity<IModel, IView, IPresenter> entity)
{
_entities.Add(entity); // not cast at all
}
// some other methods below...
}
//------->>>Main changes here - *out* TModel, etc!!!
public interface IEntity<out TModel, out TView, out TPresenter>
where TModel : IModel
where TView: IView
where TPresenter : IPresenter
{
}
public interface IPresenter{}
public interface IView{}
public interface IModel{}