我有两个接口:
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()) {}
}
规则B : 规则A : 规则<DmModel,中间,DbModel> : IRule<IDmModel,IDbModel> : IRule
当我尝试将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,>
这不能强制转换为IRule<IDmModel,IDbModel>。 C# 不支持这种类型的强制转换。 出于同样的原因,您不能执行List<object> b = (List<object>)new List<string>();
(给出"无法将类型'System.Collections.Generic.List
这是协方差的问题。
以下是Microsoft关于该主题的更多信息:https://learn.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
参数。 不幸的是,事实并非如此;由于RuleA
的具体形式,实例必须可分配给DmModel
,因此IDmModel
的其他导数将失败。