[英]C# Is Not Assignable Type - Generics
所以我只是在處理我正在處理的狀態機類型,並且大多想要嘗試使用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()的繼承類型,所以我可以確定我可以實例化它們。
我再次道歉,如果我做了一件令人難以置信的錯事,我只是碰到了一堵磚牆而且我的谷歌搜索引導我走向了不好的方向。 我沒有包含任何其他接口或類,因為它們似乎不是問題的一部分,但如果需要我可以附加它們。 謝謝你的幫助!
出現此問題是因為:
ITransitionContainer
不是其類型參數的協變接口 。 AddTransition
方法通用參數被不限制為引用類型 。 _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
可以是結構,而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 };
}
就是這樣。 :)
當然,你必須復制它工作所需的一切,在這種情況下,似乎這兩個對象就足夠了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.