问题描述
所以我只是在使用我正在研究的状态机类型,主要是想尝试一下 Activator.CreateInstance 方法来看看它是什么样的,我遇到了一个我似乎无法使用的问题我想的 where
子句.如果我只是个白痴,我提前道歉,每个人都笑我离开这里.所以我有2个小班.
So I'm just hacking around with a state machine type I was working on and mostly wanting to just try out the Activator.CreateInstance method to see what it was like, and I ran into a problem where I cant seem to use the where
clause as I would think. I apologize ahead of time if I am just an idiot and everyone laughs me out of here. So I have 2 small classes.
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;表达式类型为 TransitionContainer<ITransition,IState>
错误.
So on the line _transitions.Add(typeof(TTransition), transitionContainer);
I receive a cannot convert TransitionContainer<TTransition,TStateTo> expression to type TransitionContainer<ITransition,IState>
error.
如果我将泛型参数更改为
If I change the generic parameters to
var transitionContainer= new TransitionContainer<ITransition, IState>();
它工作正常,但我想使用 new() 的继承类型,所以我可以确定我可以实例化它们.
it works fine, but I wanted to use inherited types that are new() so I could be sure I could instantiate them.
如果我做错了什么,我再次道歉,我只是碰到了一堵砖墙,我的谷歌搜索让我没有找到好的方向.我没有包含任何其他接口或类,因为它们似乎不是问题的一部分,但如果需要我可以附加它们.感谢您的帮助!
Again I apologize if I'm doing something incredibly wrong, I was just kind of ran into a brick wall and my googling led me in no good direction. I didnt include any of the other interfaces or classes as they didn't seem to be part of the problem, but if there needed I can attach them. Thanks for any help!
推荐答案
出现这个问题是因为:
ITransitionContainer
不是 协变接口 在其类型参数上.AddTransition
方法的通用参数是不受限制 为 引用类型._transitions
不是具有ITransitionContainer
值的字典,因此无需将其更改为Dictionary>
我们仍然无法添加适当限制的协变转换.
ITransitionContainer
is not a covariant interface over its type arguments.AddTransition
method generic arguments are not constrained to be reference types._transitions
is not a dictionary withITransitionContainer
values, so without changing it toDictionary<Type, ITransitionContainer<ITransition, IState>>
we still won't be able to add even properly resticted covariant transtions.
简化示例
考虑以下简化情况:
Simplified example
Consider the following simplified case:
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 不适用于值类型一个>:
, then it will fail only in generic method. Because here TTransition
can be a struct and co/(contra)variance doesn't work with value types:
public static void Do<TTransition>()
where TTransition : ITransition
{
ITest<ITransition> item = new SomeTest<TTransition>();
}
但是,如果您使用该方法 仅限于引用类型,那么它在这两种情况下都可以工作:
But if you make that method constrained to only reference types, then it will work in both cases:
public static void Do<TTransition>()
where TTransition : class, ITransition
{
ITest<ITransition> item = new SomeTest<TTransition>();
}
将相同的原则(out
和 class
)应用于您的两个通用参数,它就可以完成这项工作.
Apply the same principle(out
and class
) to your two generic arguments and it will do the job.
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# 是不可分配的类型 - 泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!