C# Не Присваивается Тип - Дженерики
так что я просто взламываю с типом государственной машины, над которой я работал, и в основном хочу просто попробовать активатор.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, 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<TTransition,TStateTo> expression to type TransitionContainer<ITransition,IState> ошибка.
если я изменю общие параметры на
var transitionContainer= new TransitionContainer<ITransition, IState>();
он отлично работает, но я хотел использовать унаследованные типы, которые являются новыми (), чтобы я мог быть уверен, что я мог инстанцировать их.
еще раз прошу прощения, если я делаю что-то невероятно неправильно, я просто наткнулся на кирпичную стену, и мой гуглинг привел меня в плохом направлении. Я не включил ни один из других интерфейсов или классов, поскольку они не казались частью проблемы, но при необходимости я могу прикрепить их. Спасибо за любую помощь!
2 ответов
эта проблема возникает потому, что:
- 
ITransitionContainer- это не ковариантные интерфейс над его аргументами типа. - 
AddTransitionобщие аргументы метода являются не ограничено на ссылка типа. - 
_transitionsэто не словарь сITransitionContainerзначения, поэтому без изменения его наDictionary<Type, ITransitionContainer<ITransition, IState>>мы все равно не сможем добавить даже правильно д ковариантные transtions. 
рассмотрим следующий упрощенный случай:
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)не работает с типами значений:
public static void Do<TTransition>()
    where TTransition : ITransition
{
    ITest<ITransition> item = new SomeTest<TTransition>();
}
но если вы сделаете это метод ограничено только ссылочными типами, тогда он будет работать в обоих случаях:
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>> _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);
    }
}
это не удается, потому что дженерики не ковариантны. Проблему можно увидеть здесь:
TransitionContainer<ITransition, IState> value = new TransitionContainer<TTransition, TStateTo>();
это дает вам ту же ошибку. Вы также получите эту ошибку примерно так:
List<IComparable> list = new List<DateTime>();
Visual Studio говорит вам (в основном), что:
Cannot implicitly convert type 'List<System.DateTime>' to 'List<System.IComparable>'
что вам нужно сделать, это преобразовать объект. Вы можете создать Convert метод, который возвращает TransitionContainer<ITransition, IState> и затем использовать .Add(typeof(TTransition), transitionContainer.Convert()) (или как вы назвали его).
но самый безболезненный вариант создайте неявное преобразование для вашего TransitionContainer<TTransition, TStateTo> объект, добавив этот статический метод:
public static implicit operator TransitionContainer<ITransition, IState>(TransitionContainer<TTransition, TStateTo> value)
{
    return new TransitionContainer<ITransition, IState>() { StateTo = value.StateTo, Transition = value.Transition };
}
и это все. :)
конечно, вам придется скопировать все необходимое для его работы, в этом случае кажется, что этих двух объектов достаточно.