不变继承问题
我正试图实施一种战略模式,允许我将某些“收益”应用于“账户”。 在下面的代码中,我无法将接口的实现添加到期望接口的字典中。 我认为这是一种逆转问题,但我觉得我应该能够做到这一点:
编辑:
由于答案似乎是不可能的,对于如何实现我在这里的目标有什么建议?
void Main()
{
var provider = new BenefitStrategyProvider();
var freeBenefit = new FreeBenefit();
var strategy = provider.GetStrategy(freeBenefit);
strategy.ApplyBenefit(freeBenefit, new Account());
}
public class BenefitStrategyProvider
{
private Dictionary<Type, IBenefitStrategy<BenefitBase>> _strategies = new Dictionary<Type, IBenefitStrategy<BenefitBase>>();
public BenefitStrategyProvider()
{
/* Why can't I add this? */
_strategies.Add(typeof(FreeBenefit), new FreeBenefitStrategy());
}
public IBenefitStrategy<BenefitBase> GetStrategy(BenefitBase benefit)
{
return _strategies[benefit.GetType()];
}
}
public class Account {}
public abstract class BenefitBase
{
public string BenefitName {get;set;}
}
public class FreeBenefit : BenefitBase {}
public interface IBenefitStrategy<T> where T: BenefitBase
{
void ApplyBenefit(T benefit, Account account);
}
public class FreeBenefitStrategy : IBenefitStrategy<FreeBenefit>
{
public void ApplyBenefit(FreeBenefit benefit, Account account)
{
Console.WriteLine("Free Benefit applied");
}
}
编辑 - 格式引擎已经删除了<angled brackets>
所有内容,这使得它不可能理解。 对不起,如果这是混乱!
FreeBenefitStrategy
实现IBenefitStrategy<FreeBenefit>
。 它只能应用FreeBenefits
,而不能带来其他任何好处。 它不是IBenefitStrategy<BenefitBase>
,所以你不能把它放在这些集合中。 从逻辑上讲, IBenefiteStrategy
在IBenefiteStrategy
可能是BenefitBase
,但这对您并没有帮助 - IBenefitStrategy<BenefitBase>
声称可以应用各种好处,因此IBenefitStrategy<BenefitBase>
是IBenefitStrategy<FreeBenefit>
,但反过来是不正确的 - 一个IBenefitStrategy<FreeBenefit>
不能应用任何BenefitBase
。
我不认为有什么方法可以在不使用类型转换的情况下获得像您想要的异构集合。 如果你仔细想想,你不能在IBenefitStrategy<FreeBenefit>
和IBenefitStrategy<ExpensiveBenefit>
上调用超出它们从对象中共享的方法,所以它是有道理的,只有类型对象的变量是唯一可以指向任一。 如果你想让它们保持在同一个词典中,你需要把它作为一个Dictionary<Type, object>
。 您可以将GetStrategy
更改为泛型并应用适当的类型转换,但在查找字典时要小心 - 想想如果传入的对象是FreeBenefit
的子类,会发生什么情况。
请参阅:协变和逆变常见问题解答
How can I create variant generic interfaces and delegates myself? The out keyword marks a type parameter as covariant, and the in keyword marks it as contravariant. The two most important rules to remember: You can mark a generic type parameter as covariant if it is used only as a method return type and is not used as a type of formal method parameters. And vice versa, you can mark a type as contravariant if it is used only as a type of formal method parameters and not used as a method return type.
您需要将T添加到您的界面中:
public interface IBenefitStrategy<in T>
链接地址: http://www.djcxy.com/p/6705.html
上一篇: Invariant inheritance problem
下一篇: Events ending too early when 15 minute slotMinutes set in FullCalendar