我正在尝试实现一种策略模式,以允许我将一些“好处”应用到“帐户”。在下面的代码中,我无法将接口(interface)的实现添加到需要接口(interface)的字典中。我认为这是某种逆变问题,但感觉我应该能够做到这一点:
编辑:
由于答案似乎是不可能的,关于如何实现我在这里的目标有什么建议吗?
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
在 BenefitBase
中可能是逆变的,但这对你没有帮助 - IBenefitStrategy<BenefitBase>
声称能够申请所有种福利,所以IBenefitStrategy<BenefitBase>
是一个IBenefitStrategy<FreeBenefit>
,但反之则不然 - IBenefitStrategy<FreeBenefit>
不能应用任何 BenefitBase
.
我认为如果不使用类型转换,就无法获得您想要的异构集合。如果您考虑一下,没有任何方法可以同时在 IBenefitStrategy<FreeBenefit>
上调用。和一个 IBenefitStrategy<ExpensiveBenefit>
超出了它们从对象共享的那些,因此类型对象的变量是唯一可以指向其中任何一个的变量是有道理的。如果您想将它们保存在同一个字典中,则需要将其设为 Dictionary<Type, object>
.你可以改变 GetStrategy
通用并应用适当的类型转换,但在查找字典时要小心 - 想想如果传入的对象是 FreeBenefit
的子类会发生什么.
关于c# - 不变继承问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5918649/