Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将泛型对象添加到泛型集合时出现编译时错误_C#_Generics - Fatal编程技术网

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

C# 将泛型对象添加到泛型集合时出现编译时错误,c#,generics,C#,Generics,我们已经到了无法继续下去的地步: 简称: 我们有一个通用接口和一组通用接口。尝试将通用接口的实现添加到集合失败。发生的情况是,我得到一个编译时异常,它说: 无法从TestApp.IState'转换为TestApp.IState' 长[代码示例]: class Program { static void Main(string[] args) { var coll = new StateCollection(); var state = new So

我们已经到了无法继续下去的地步:

简称: 我们有一个通用接口和一组通用接口。尝试将通用接口的实现添加到集合失败。发生的情况是,我得到一个编译时异常,它说:

无法从TestApp.IState'转换为TestApp.IState'

长[代码示例]:

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.AddStatestate' 同样的事情也发生在另一个地方

编辑2:
问题我没有给出正确的例子。Out IState不是一个接口,而是一个抽象类。非常抱歉!将代码更改为使用抽象类这看起来更像是Add函数的参数错误。您是否尝试过在不使用泛型的情况下声明add函数?继承本身应该允许它。使AddState函数如下所示:

按照Edit2进行编辑:

如前所述,继承本身应该处理泛型。只要您声明的任何类正确实现了IView或IState,那么就不会有任何问题

public absract class StateBase
{
    public IView view { get; set; }

    ....
}

public Interface IView
{ ... }

public class StateCollection
{
    private List<StateBase> _states = new List<StateBase>();

    public void AddState(StateBase state)
    {
        _states.Add(state);
    }
}

public class SomeView : IView
{ ... }
在本例中,SomeState仍然是IState对象,所有IState对象都实现IView,而SomeView是IView对象。SomeState在内部实现SomeView。对我来说看起来是一样的,但是我不知道这个改编对你的真实代码有多好

任何其他类都将遵循相同的模型。该州将实现StateBase,并在内部声明一个自定义视图,该视图本身需要扩展IView。这样,自定义视图上的IView强制转换将起作用

评论如下:


这看起来更像是Add函数的参数错误。您是否尝试过在不使用泛型的情况下声明add函数?继承本身应该允许它。使AddState函数如下所示:

按照Edit2进行编辑:

如前所述,继承本身应该处理泛型。只要您声明的任何类正确实现了IView或IState,那么就不会有任何问题

public absract class StateBase
{
    public IView view { get; set; }

    ....
}

public Interface IView
{ ... }

public class StateCollection
{
    private List<StateBase> _states = new List<StateBase>();

    public void AddState(StateBase state)
    {
        _states.Add(state);
    }
}

public class SomeView : IView
{ ... }
在本例中,SomeState仍然是IState对象,所有IState对象都实现IView,而SomeView是IView对象。SomeState在内部实现SomeView。对我来说看起来是一样的,但是我不知道这个改编对你的真实代码有多好

任何其他类都将遵循相同的模型。该州将实现StateBase,并在内部声明一个自定义视图,该视图本身需要扩展IView。这样,自定义视图上的IView强制转换将起作用

评论如下:

第一种解决方案

第二种解决方案:在类StateCollection中保留更改

将接口IState更改为

并将某个状态分类为

public class SomeState : IState<SomeView>
    {
        public SomeView View{ get;private set; }
    }
Edit2的解决方案:

第一种解决方案

第二种解决方案:在类StateCollection中保留更改

将接口IState更改为

并将某个状态分类为

public class SomeState : IState<SomeView>
    {
        public SomeView View{ get;private set; }
    }
Edit2的解决方案:


这些变化如何:

public class SomeState : IState<SomeView>
{
    public SomeView View
    {
        get;
        set;
    }
} 
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; }
}

这些变化如何:

public class SomeState : IState<SomeView>
{
    public SomeView View
    {
        get;
        set;
    }
} 
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; }
}

添加接口IState non-generic并从IState继承它。然后将_states声明为List,方法addStateState state添加接口IState non-generic并从IState继承它。然后将_states声明为List,方法addStateState state编辑:您只需要让StateBase从协变接口继承。你不能让一个类直接协变,你必须通过一个接口

试试这个:

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 class SomeView : IView
{
}

public interface IState<out T> where T : IView // now covariant with T
{
    T View { get; }
}

public abstract class StateBase<T> : IState<T> where T : IView
{
    public T View { get; set; }
}

public interface IView
{
}

编辑:您只需要让StateBase从协变接口继承。你不能让一个类直接协变,你必须通过一个接口

试试这个:

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 class SomeView : IView
{
}

public interface IState<out T> where T : IView // now covariant with T
{
    T View { get; }
}

public abstract class StateBase<T> : IState<T> where T : IView
{
    public T View { get; set; }
}

public interface IView
{
}

您使用的是什么版本的C?C<3.0与泛型没有差异。这是因为IState不是IState>\u states定义为,但您试图将IState添加到该集合中。@sll SomeView确实实现了IView@Oded我使用的是.NET 4.0版,您使用的是哪个版本的C?C<3.0与泛型没有差异。这是因为IState不是IState>\u states定义为,但您试图将IState添加到该集合中。@sll SomeView确实实现了IView@Oded我使用的是.NET 4.0版。在您发布本期文章的同时,我正在编辑文章。这也不行。当我这样做时,我只是得到了“TestApp.StateCollection.AddStateTestApp.IState”的最佳重载方法匹配,在调用AddState时有一些无效的参数请参见EDIT1I尝试状态为IState,但它只返回null,如中所示,转换失败如果转换失败,则意味着代码无法将SomeState识别为的正确实例
IState,否则你可以投下它。这似乎是问题的根源,继承并没有像模板一样正常工作。是的,这似乎是个问题,但我们为什么以及如何解决这个问题?我现在真正的问题是:删除模板会破坏任何其他现有代码,只要假设IView和StateBase及其关系保持不变,我就在你发布这期文章的同时编辑了这篇文章。这也不行。当我这样做的时候,我只得到了“TestApp.StateCollection.AddStateTestApp.IState”的最佳重载方法匹配,调用AddState时有一些无效参数请参见EDIT1I尝试状态为IState,但它只返回null,如中所示,强制转换失败如果强制转换失败,这意味着代码不能将SomeState识别为IState的正确实例,否则您可以强制转换它。这似乎是问题的根源,继承并没有像模板一样正常工作。是的,这似乎是个问题,但我们为什么以及如何解决这个问题?我现在真正的问题是:删除模板会破坏任何其他现有代码,只要假设IView和StateBase及其关系保持不变,您所要求的是哪一个仅适用于接口和委托。唯一的机会是将抽象类提取到一个接口中。您所要求的是哪一个仅适用于接口和委托。唯一的机会是将抽象类提取到接口中。@mrseundless然后。。。实际上,它不起作用,因为您不能在接口和委托之外使用协方差。@MrSoundless好的,请参阅Edit2的解决方案,也许可以。@MrSoundless那么。。。实际上,它不起作用,因为您不能在接口和委托之外使用协方差。@MrSoundless很好,请参阅Edit2的解决方案,也许可以。@MrSoundless请参阅edit来回答。如果您可以通过从协变接口添加继承来更改抽象类的定义,那么您仍然可以这样做work@MrSoundless请参见编辑以回答问题。如果您可以通过从协变接口添加继承来更改抽象类的定义,那么仍然可以使其工作
public interface IState<out T> where T : IView
{
    T View { get; }
}
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; }
}
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 class SomeView : IView
{
}

public interface IState<out T> where T : IView // now covariant with T
{
    T View { get; }
}

public abstract class StateBase<T> : IState<T> where T : IView
{
    public T View { get; set; }
}

public interface IView
{
}