[英]Unable to cast object of generic type to generic interface C#
我有兩個接口:
public interface IDbModel {}
public interface IDmModel {}
和派生自這的類:
public class DbModel : IDbModel {}
public class DmModel : IDmModel {}
public class Middle { }
另外我有兩個限制接口:
public interface IRule { }
public interface IRule<in TInput, out TOutput> : IRule
where TInput : IDmModel
where TOutput : IDbModel
{
TOutput Apply(TInput elem);
}
從這個接口派生出一個抽象類:
public abstract class Rule<TDmModel, TMiddle, TDb> : IRule<TDmModel, TDb>
where TDmModel : IDmModel
where TDb : IDbModel
{
private readonly Func<TDmModel, TMiddle> _rule;
protected Rule(Func<TDmModel, TMiddle> rule) { _rule = rule; }
protected abstract TDb Apply(TMiddle transformedMessage);
public TDb Apply(TDmModel elem) { ... }
}
在此之后,我創建了兩個派生自此抽象類的類:
public class RuleA : Rule<DmModel, Middle, DbModel>
{
public RuleA(Func<DmModel, Middle> rule) : base(rule) {}
protected override DbMode Apply(Middle transformedMessage) { ... }
}
public class RuleB : RuleA
{
public RuleB() : base((dm) => new Middle()) {}
}
RuleB:RuleA:Rule <DmModel,Middle,DbModel>:IRule <IDmModel,IDbModel>:IRule
當我嘗試將RuleB
對象RuleB
為IRule<IDmModel, IDbModel>
出現未處理的異常
無法將類型為'ParsreCombinators.RuleB'的對象轉換為'ParsreCombinators.IRule`2 [ParsreCombinators.IDmModel,ParsreCombinators.IDbModel]'。
var ruleB = (IRule<IDmModel, IDbModel>)new RuleB(); // Exception
IDbModel dbModel = ruleB.Apply(new DmModel());
有什么不對這個
為了減少混亂,我簡化了它:
編輯:
在我理解了答案之后,問題是什么,並使示例不那么混亂我簡化它:
public interface IDbModel {}
public interface IDmModel {}
public class DbModel : IDbModel {}
public class DmModel : IDmModel {}
public interface IRule<in TInput, out TOutput>
where TInput : IDmModel
where TOutput : IDbModel
{
TOutput Apply(TInput elem);
}
public class RuleA : IRule<DmModel, DbModel>
{
public DbModel Apply(DmModel elem) { ... }
}
var ruleA = (IRule<IDmModel, IDbModel>)new RuleA(); // Exception
你到那里的間接程度很高......
這是問題所在:
public abstract class Rule<TDmModel, TMiddle, TDb> : IRule<TDmModel, TDb>
where TDmModel : IDmModel
where TDb : IDbModel
public class RuleA : Rule<DmModel, Middle, DbMode>
public class RuleB : RuleA
...
var ruleB = (IRule<IDmModel, IDbModel>)new RuleB();
RuleB實現了IRule <DmModel,DbMode>
這不能轉換為IRule <IDmModel,IDbModel>。 C#不支持這種類型的轉換。 出於同樣的原因,你不能做List<object> b = (List<object>)new List<string>();
(提供“無法將類型'System.Collections.Generic.List <string>轉換為System.Collections.Generic.List <object>。”)
這是協方差的問題。
以下是Microsoft提供的有關此主題的更多信息: https : //docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance
這是一個非常令人困惑的例子,但我相信問題是你正在轉換為泛型類型並給它接口,當你派生的類強制你使用DmModel和DbMode時。
也許這就是你的意思:
var ruleB = (IRule<DmModel, DbMode>)new RuleB();
編譯得很好,我用這種方式構建你的類,是重組之外的唯一選擇。
你的界面IRule<in TInput, out TOutput>
既是協變的又是逆變的,這意味着你無法共同演變它。 逆變阻止了這種情況。
基本上,你的賦值var dbModel = (IRule<IDmModel, IDbModel>)new RuleB();
斷言dbModel必須接受任何 IDmModel
參數。 不幸的是,事實並非如此; 實例必須分配給DmModel
由於的具體形式RuleA
,如此其它衍生物IDmModel
會失敗。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.