所以我只是在研究我正在研究的状态机类型,主要是想尝试一下 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, 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>();
它工作正常,但我想使用 new() 的继承类型,所以我可以确定我可以实例化它们。
如果我做错了什么,我再次道歉,我只是碰壁了,我的谷歌搜索没有把我引向正确的方向。我没有包含任何其他接口(interface)或类,因为它们似乎不是问题的一部分,但如果需要,我可以附加它们。感谢您的帮助!
最佳答案
出现这个问题是因为:
-
ITransitionContainer
不是 covariant interface在其类型参数上。 -
AddTransition
方法通用参数是 not constrained待reference types . -
_transitions
不是ITransitionContainer
的字典值,因此无需将其更改为Dictionary<Type, ITransitionContainer<ITransition, IState>>
我们仍然无法添加甚至适当限制的协变转换。
简化示例
考虑以下简化情况:
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 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>> _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# 不是可分配类型 - 泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38035427/