C# 是不可分配的类型 - 泛型 [英] C# Is Not Assignable Type - Generics

查看:23
本文介绍了C# 是不可分配的类型 - 泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我只是在使用我正在研究的状态机类型,主要是想尝试一下 Activator.CreateInstance 方法来看看它是什么样的,我遇到了一个我似乎无法使用的问题我想的 where 子句.如果我只是个白痴,我提前道歉,每个人都笑我离开这里.所以我有2个小班.

So I'm just hacking around with a state machine type I was working on and mostly wanting to just try out the Activator.CreateInstance method to see what it was like, and I ran into a problem where I cant seem to use the where clause as I would think. I apologize ahead of time if I am just an idiot and everyone laughs me out of here. So I have 2 small classes.

public class TransitionContainer<TTransition, TStateTo> :
    ITransitionContainer<TTransition, TStateTo>
    where TTransition : ITransition
    where TStateTo : IState
{
    public TransitionContainer()
    {
        StateTo = typeof(TStateTo);
        Transition = Activator.CreateInstance<TTransition>();
    }

    public Type StateTo { get; private set; }

    public TTransition Transition { get; private set; }
}

还有

  public class StateContainer<T> : IStateContainer<T> where T : IState
{
    private Dictionary<Type, TransitionContainer<ITransition, IState>> _transitions =
        new Dictionary<Type, TransitionContainer<ITransition, IState>>();

    public StateContainer()
    {
        State = Activator.CreateInstance<T>();
    }

    public T State { get; private set; }

    public int TransitionCount
    {
        get { return _transitions.Count; }
    }


    public void AddTransition<TTransition, TStateTo>() where TTransition : ITransition, new()
        where TStateTo : IState, new()
    {
        var transitionContainer= new TransitionContainer<TTransition, TStateTo>();

        _transitions.Add(typeof(TTransition), transitionContainer);
    }

所以上线 _transitions.Add(typeof(TTransition), transitionContainer); 我收到一个 cannot convert TransitionContainer;表达式类型为 TransitionContainer<ITransition,IState> 错误.

So on the line _transitions.Add(typeof(TTransition), transitionContainer); I receive a cannot convert TransitionContainer<TTransition,TStateTo> expression to type TransitionContainer<ITransition,IState> error.

如果我将泛型参数更改为

If I change the generic parameters to

var transitionContainer= new TransitionContainer<ITransition, IState>();

它工作正常,但我想使用 new() 的继承类型,所以我可以确定我可以实例化它们.

it works fine, but I wanted to use inherited types that are new() so I could be sure I could instantiate them.

如果我做错了什么,我再次道歉,我只是碰到了一堵砖墙,我的谷歌搜索让我没有找到好的方向.我没有包含任何其他接口或类,因为它们似乎不是问题的一部分,但如果需要我可以附加它们.感谢您的帮助!

Again I apologize if I'm doing something incredibly wrong, I was just kind of ran into a brick wall and my googling led me in no good direction. I didnt include any of the other interfaces or classes as they didn't seem to be part of the problem, but if there needed I can attach them. Thanks for any help!

推荐答案

出现这个问题是因为:

  1. ITransitionContainer 不是 协变接口 在其类型参数上.
  2. AddTransition 方法的通用参数是不受限制引用类型.
  3. _transitions 不是具有 ITransitionContainer 值的字典,因此无需将其更改为 Dictionary>我们仍然无法添加适当限制的协变转换.
  1. ITransitionContainer is not a covariant interface over its type arguments.
  2. AddTransition method generic arguments are not constrained to be reference types.
  3. _transitions is not a dictionary with ITransitionContainer values, so without changing it to Dictionary<Type, ITransitionContainer<ITransition, IState>> we still won't be able to add even properly resticted covariant transtions.

简化示例

考虑以下简化情况:

Simplified example

Consider the following simplified case:

public interface ITransition
{

}

public class SomeTransition : ITransition
{

}

public interface ITest<TTransition>
    where TTransition : ITransition
{
    TTransition Value { get; }
}


public class SomeTest<TTransition> : ITest<TTransition>
    where TTransition : ITransition
{
    public TTransition Value
    {
        get
        {
            throw new NotImplementedException();
        }
    }
}

两者都会失败

public static void Do<TTransition>()
    where TTransition : ITransition
{
    ITest<ITransition> item = new SomeTest<TTransition>();
}

ITest<ITransition> item = new SomeTest<SomeTransition>();

如果你使 ITest 协变

public interface ITest<out TTransition>

,那么它只会在泛型方法中失败.因为这里 TTransition 可以是结构体和 co/(contra)variance 不适用于值类型:

, then it will fail only in generic method. Because here TTransition can be a struct and co/(contra)variance doesn't work with value types:

public static void Do<TTransition>()
    where TTransition : ITransition
{
    ITest<ITransition> item = new SomeTest<TTransition>();
}

但是,如果您使用该方法 仅限于引用类型,那么它在这两种情况下都可以工作:

But if you make that method constrained to only reference types, then it will work in both cases:

public static void Do<TTransition>()
    where TTransition : class, ITransition
{
    ITest<ITransition> item = new SomeTest<TTransition>();
}

将相同的原则(outclass)应用于您的两个通用参数,它就可以完成这项工作.

Apply the same principle(out and class) to your two generic arguments and it will do the job.

public interface IState
{    }

public interface ITransition
{    }

// !!!!! - Here we add out specifier
public interface ITransitionContainer<out TTransition, out TStateTo>
    where TTransition : ITransition
    where TStateTo : IState
{
    Type StateTo
    {
        get;
    }

    TTransition Transition
    {
        get;
    }
}

public interface IStateContainer<T> where T : IState
{
    T State
    {
        get;
    }
}


public class TransitionContainer<TTransition, TStateTo> : ITransitionContainer<TTransition, TStateTo>
    where TTransition : ITransition
    where TStateTo : IState
{
    public TransitionContainer()
    {
        StateTo = typeof(TStateTo);
        Transition = Activator.CreateInstance<TTransition>();
    }

    public Type StateTo { get; private set; }

    public TTransition Transition { get; private set; }
}


public class StateContainer<T> : IStateContainer<T> where T : IState
{
    private Dictionary<Type, ITransitionContainer<ITransition, IState>> _transitions =
        new Dictionary<Type, ITransitionContainer<ITransition, IState>>();

    public StateContainer()
    {
        State = Activator.CreateInstance<T>();
    }

    public T State { get; private set; }

    public int TransitionCount
    {
        get { return _transitions.Count; }
    }

    public void AddTransition<TTransition, TStateTo>()
        // !!!!!! - Here we add class constraints
        where TTransition : class, ITransition, new()
        where TStateTo : class, IState, new()
    {
        var transitionContainer = new TransitionContainer<TTransition, TStateTo>();

        _transitions.Add(typeof(TTransition), transitionContainer);
    }
}

这篇关于C# 是不可分配的类型 - 泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆