[英]Unable to cast object of generic type to generic interface C#
I have two interfaces: 我有两个接口:
public interface IDbModel {}
public interface IDmModel {}
And classes derived from this: 和派生自这的类:
public class DbModel : IDbModel {}
public class DmModel : IDmModel {}
public class Middle { }
Also I have two interfaces with restrictions: 另外我有两个限制接口:
public interface IRule { }
public interface IRule<in TInput, out TOutput> : IRule
where TInput : IDmModel
where TOutput : IDbModel
{
TOutput Apply(TInput elem);
}
And one abstract class derived from this interface: 从这个接口派生出一个抽象类:
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) { ... }
}
After this I created two classes derived from this abstract class: 在此之后,我创建了两个派生自此抽象类的类:
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:RuleA:Rule <DmModel,Middle,DbModel>:IRule <IDmModel,IDbModel>:IRule
And when I try to cast object of RuleB
to IRule<IDmModel, IDbModel>
occours unhandled exception 当我尝试将
RuleB
对象RuleB
为IRule<IDmModel, IDbModel>
出现未处理的异常
Unable to cast object of type 'ParsreCombinators.RuleB' to type 'ParsreCombinators.IRule`2[ParsreCombinators.IDmModel,ParsreCombinators.IDbModel]'.
无法将类型为'ParsreCombinators.RuleB'的对象转换为'ParsreCombinators.IRule`2 [ParsreCombinators.IDmModel,ParsreCombinators.IDbModel]'。
var ruleB = (IRule<IDmModel, IDbModel>)new RuleB(); // Exception
IDbModel dbModel = ruleB.Apply(new DmModel());
To make the example less confusing I simplify it: 为了减少混乱,我简化了它:
EDIT: 编辑:
After the answers I understood, what is the problem and to make the example less confusing I simplify it: 在我理解了答案之后,问题是什么,并使示例不那么混乱我简化它:
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
That's a lot of levels of indirection you got there... 你到那里的间接程度很高......
Here's the issue: 这是问题所在:
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 implements IRule<DmModel, DbMode> RuleB实现了IRule <DmModel,DbMode>
This cannot be cast to IRule<IDmModel, IDbModel>. 这不能转换为IRule <IDmModel,IDbModel>。 C# does not support this type of casting.
C#不支持这种类型的转换。 For the same reason, you cannot do
List<object> b = (List<object>)new List<string>();
出于同样的原因,你不能做
List<object> b = (List<object>)new List<string>();
(Gives "Cannot convert type 'System.Collections.Generic.List<string> to System.Collections.Generic.List<object>.") (提供“无法将类型'System.Collections.Generic.List <string>转换为System.Collections.Generic.List <object>。”)
This is an issue with covariance. 这是协方差的问题。
Here is some more information from Microsoft on the subject: https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance 以下是Microsoft提供的有关此主题的更多信息: https : //docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance
This is a pretty confusing example, but I believe the problem is you're casting to a generic type and giving it interfaces, when the classes your deriving from are forcing you to use DmModel and DbMode. 这是一个非常令人困惑的例子,但我相信问题是你正在转换为泛型类型并给它接口,当你派生的类强制你使用DmModel和DbMode时。
Perhaps this is what you meant: 也许这就是你的意思:
var ruleB = (IRule<DmModel, DbMode>)new RuleB();
That compiles just fine, and I with that way your classes are structured, is the only option other than restructuring. 编译得很好,我用这种方式构建你的类,是重组之外的唯一选择。
Your interface IRule<in TInput, out TOutput>
is both covariant and contravariant, which means you can't covariantly cast it. 你的界面
IRule<in TInput, out TOutput>
既是协变的又是逆变的,这意味着你无法共同演变它。 The contravariance prevents this. 逆变阻止了这种情况。
Basically, your assignment var dbModel = (IRule<IDmModel, IDbModel>)new RuleB();
基本上,你的赋值
var dbModel = (IRule<IDmModel, IDbModel>)new RuleB();
asserts that dbModel must accept any IDmModel
parameter. 断言dbModel必须接受任何
IDmModel
参数。 Unfortunately, this is not true; 不幸的是,事实并非如此; instances must be assignable to
DmModel
due to the concrete form of RuleA
, so other derivatives of IDmModel
would fail. 实例必须分配给
DmModel
由于的具体形式RuleA
,如此其它衍生物IDmModel
会失败。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.