无法将泛型类型的对象强制转换为通用接口C#

kog*_*oia 5 c# generics inheritance multiple-inheritance

我有两个接口:

public interface IDbModel {}
public interface IDmModel {}
Run Code Online (Sandbox Code Playgroud)

和派生自这的类:

public class DbModel : IDbModel {}
public class DmModel : IDmModel {}
public class Middle { }
Run Code Online (Sandbox Code Playgroud)

另外我有两个限制接口:

public interface IRule { }
public interface IRule<in TInput, out TOutput> : IRule
    where TInput : IDmModel
    where TOutput : IDbModel
{
    TOutput Apply(TInput elem);
}
Run Code Online (Sandbox Code Playgroud)

从这个接口派生出一个抽象类:

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) { ... }
}
Run Code Online (Sandbox Code Playgroud)

在此之后,我创建了两个派生自此抽象类的类:

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()) {}
}
Run Code Online (Sandbox Code Playgroud)

RuleB:RuleA:Rule <DmModel,Middle,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());
Run Code Online (Sandbox Code Playgroud)

有什么不对这个

为了减少混乱,我简化了它:

编辑:

在我理解了答案之后,问题是什么,并使示例不那么混乱我简化它:

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
Run Code Online (Sandbox Code Playgroud)

Chr*_*ger 7

你到那里的间接程度很高......

这是问题所在:

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();
Run Code Online (Sandbox Code Playgroud)

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