所以我只是在处理我正在处理的状态机类型,并且大多想要尝试使用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()的继承类型,所以我可以确定我可以实例化它们。
我再次道歉,如果我做了一件令人难以置信的错事,我只是碰到了一堵砖墙而且我的谷歌搜索引导我走向了不好的方向。我没有包含任何其他接口或类,因为它们似乎不是问题的一部分,但如果需要我可以附加它们。谢谢你的帮助!
答案 0 :(得分:4)
出现此问题是因为:
ITransitionContainer
与其类型参数不是covariant interface。 AddTransition
方法通用参数not constrained为reference 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
可以是结构和共同/(反)方差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);
}
}
答案 1 :(得分:2)
失败是因为泛型不是协变的。这个问题可以在这里看到:
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 };
}
就是这样。 :)
当然,你必须复制它所需要的一切,在这种情况下,似乎这两个对象就足够了。