Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Downcasting/Upcasting interface with generics to same interface but with different generics – C#

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel


// 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.

>Solution :

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 ();

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

    //------->>>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
    {
    }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading