简体   繁体   English

将 generics 的接口向下转换/向上转换为相同的接口,但具有不同的 generics - C#

[英]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.我想将接口IEntity<TM, TV, TP>向下转换为IEntity<IModel, IView, IPresenter> ,但它给了我 Invalid Cast Exception。 I added some constraints (where) , but it also didn't help.我添加了一些约束(where) ,但它也没有帮助。

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.这个例子我想添加 IEntity 到列表。 Class has a List of IEntity<IModel, IView, IPresenter> , but it is a problem to add IEntity with generic parameters. Class 有一个IEntity<IModel, IView, IPresenter>的List,但是用通用参数添加IEntity是个问题。 Eg IEntity<ImplModel, ImplView, ImplPresenter , because it can't be downcasted/upcasted to <IEntity<IModel, IView, IPresenter>>例如IEntity<ImplModel, ImplView, ImplPresenter ,因为它不能向下转换/向上转换为 <IEntity<IModel, IView, IPresenter>>

ImplModel, ImplView, ImplPresenter- they all Impl ements its interfaces respectively (IModel, IView, IPresenter) ImplModel、 ImplView 、ImplPresenter——它们都分别实现了它的接口(IModel、IView、IPresenter)

I did some research.我做了一些研究。 Looks like I need to use something called generics covariance .看起来我需要使用一种叫做 generics协方差的东西。 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.根据文档,我需要输入输出class。但我有特定 generics的列表,输入输出无济于事。


Any help will be helpfull.任何帮助都会有所帮助。 Thanks.谢谢。

You can add out specifier into your IEntity interface declaration and then remove cast completely您可以将out符添加到您的IEntity接口声明中,然后完全删除强制转换

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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