C#不可分配类型 – 泛型

所以我只是在处理我正在处理的状态机类型,并且大多想要尝试使用Activator.CreateInstance方法来查看它是什么样的,我遇到了一个问题,我似乎无法使用where子句正如我想的那样.如果我只是个白痴,我会提前道歉,大家都会把我从这里拉出来.所以我有2个小班.
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,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);我收到一个无法转换的TransitionContainer< TTransition,TStateTo>表达式类型TransitionContainer< ITransition,IState>错误.

如果我将通用参数更改为

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

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

我再次道歉,如果我做了一件令人难以置信的错事,我只是碰到了一堵砖墙而且我的谷歌搜索引导我走向了不好的方向.我没有包含任何其他接口或类,因为它们似乎不是问题的一部分,但如果需要我可以附加它们.谢谢你的帮助!

解决方法

出现此问题是因为:

> ITransitionContainer不是类型参数的covariant interface.
> AddTransition方法泛型参数是not constrainedreference types.
> _transitions不是具有ITransitionContainer值的字典,因此不将其更改为Dictionary< Type,ITransitionContainer< ITransition,IState>>我们仍然无法添加适当的resticted协变转换.

简化示例

考虑以下简化案例:

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)方差doesn’t work with value types

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

但是,如果您使用该方法constrained to only reference types,那么它将在两种情况下都有效:

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

将相同的原则(out和class)应用于您的两个通用参数,它将完成这项工作.

针对您具体案例的完整解决方

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

    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,transitionContainer);
    }
}

相关文章

在项目中使用SharpZipLib压缩文件夹的时候,遇到如果目录较深,则压缩包中的文件夹同样比较深的问题。比...
项目需要,几十万张照片需要计算出每个照片的特征值(调用C++编写的DLL)。 业务流程:选择照片...
var array = new byte[4]; var i = Encoding.UTF8.GetBytes(100.ToString(&quot;x2&quot;));//...
其实很简单,因为Combox的Item是一个K/V的object,那么就可以把它的items转换成IEnumerable&lt;Dic...
把.net4.6安装包打包进安装程序。 关键脚本如下: 头部引用字符串对比库 !include &quot;WordFunc....
项目需求(Winform)可以批量打印某个模板,经过百度和摸索,使用iTextSharp+ZXing.NetʿreeSp...