Tra*_*ott 6 c# generics polymorphism
所以我只是在使用我正在处理的状态机类型,并且大多想要尝试使用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; }
}
Run Code Online (Sandbox Code Playgroud)
以及
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);
}
Run Code Online (Sandbox Code Playgroud)
所以在线上_transitions.Add(typeof(TTransition), transitionContainer);我收到一个cannot convert TransitionContainer<TTransition,TStateTo> expression to type TransitionContainer<ITransition,IState>错误.
如果我将通用参数更改为
var transitionContainer= new TransitionContainer<ITransition, IState>();
Run Code Online (Sandbox Code Playgroud)
它工作正常,但我想使用new()的继承类型,所以我可以确定我可以实例化它们.
我再次道歉,如果我做了一件令人难以置信的错事,我只是碰到了一堵砖墙而且我的谷歌搜索引导我走向了不好的方向.我没有包含任何其他接口或类,因为它们似乎不是问题的一部分,但如果需要我可以附加它们.谢谢你的帮助!
出现此问题的原因是:
ITransitionContainer不是其类型参数的协变接口。AddTransition方法泛型参数不限于引用类型。_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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
两者都会失败
public static void Do<TTransition>()
where TTransition : ITransition
{
ITest<ITransition> item = new SomeTest<TTransition>();
}
Run Code Online (Sandbox Code Playgroud)
和
ITest<ITransition> item = new SomeTest<SomeTransition>();
Run Code Online (Sandbox Code Playgroud)
如果你做ITest协变
public interface ITest<out TTransition>
Run Code Online (Sandbox Code Playgroud)
,那么它只会在通用方法中失败。因为这里TTransition可以是一个结构体,而 co/(contra)variance不适用于值类型:
public static void Do<TTransition>()
where TTransition : ITransition
{
ITest<ITransition> item = new SomeTest<TTransition>();
}
Run Code Online (Sandbox Code Playgroud)
但是,如果您将该方法限制为仅引用类型,那么它在两种情况下都可以工作:
public static void Do<TTransition>()
where TTransition : class, ITransition
{
ITest<ITransition> item = new SomeTest<TTransition>();
}
Run Code Online (Sandbox Code Playgroud)
将相同的原则(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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
588 次 |
| 最近记录: |