Skip to main content
 首页 » 编程设计

c#之将泛型对象添加到泛型集合时出现编译时错误

2024年02月02日29zhwl

我们已经到了不知道如何继续的地步:

简短: 我们有一个通用接口(interface)和一个通用接口(interface)的集合。尝试将通用接口(interface)的实现添加到集合失败。发生的事情是我得到一个编译时异常说:

cannot convert from TestApp.IState<T>' to TestApp.IState<TestApp.IView>'

LONG [代码示例]:

class Program 
{ 
    static void Main(string[] args) 
    { 
        var coll = new StateCollection(); 
        var state = new SomeState(); 
        coll.AddState(state); 
    } 
} 
 
public class StateCollection 
{ 
    private List<StateBase<IView>> _states = new List<StateBase<IView>>(); 
 
    public void AddState<T>(StateBase<T> state) where T: IView 
    { 
        _states.Add(state); 
    } 
} 
 
public class SomeState : StateBase<SomeView> 
{ 
 
    public IView View 
    { 
        get; 
    } 
} 
 
public class SomeView : IView 
{ 
} 
 
public abstract class StateBase<T> where T : IView 
{ 
    private SomeView _view; 
    public SomeView View 
    { 
        get { return _view; } 
    } 
} 
 
public interface IView 
{ 
} 

为什么会这样?在 AddState 中,我们提到 T 必须是 IState 的一个实例。有人可以帮助我们了解为什么会发生这种情况以及如何做我们想做的事情吗?

编辑1: 我们也试过:

    public void AddState(IState<IView> state) 
    { 
        _states.Add(state); 
    } 

但这只是将编译时错误移至“coll.AddState(state)” 所以同样的事情发生在另一个地方。

编辑2: 问题!我没有给出正确的例子。 Out IState 不是一个接口(interface)而是一个抽象类。非常抱歉!更改代码以使用抽象类

请您参考如下方法:

这些变化如何:

public class SomeState : IState<SomeView> 
{ 
    public SomeView View 
    { 
        get; 
        set; 
    } 
}  

在 AddState 方法中使用 IView 而不是使用泛型 Type T

public void AddState(IState<IView> state) 
{ 
    _states.Add(state); 
} 

使用 out 关键字使 IState 中的 T 协变

public interface IState<out T> where T : IView 
{ 
    T View { get; } 
} 

EDIT2 的解决方案:

不知道你是否适合,但你可以。

public class StateCollection 
{ 
    private List<IState<IView>> _states = new List<IState<IView>>(); 
 
    public void AddState(IState<IView> state) 
    { 
        _states.Add(state); 
    } 
} 
 
public class SomeState : StateBase<SomeView> 
{ 
    public override SomeView View 
    { 
        get { return null; } 
    } 
} 
 
public abstract class StateBase<T> : IState<T> where T : IView 
{ 
   public abstract T View { get; } 
} 
 
public interface IState<out T> where T : IView 
{ 
    T View { get; } 
}