C# 如何使用泛型实现此功能?
我没有使用.Net泛型的经验。我正在为投资控股公司在.NET4.0中设计一个软件系统。公司拥有零售业务和智能照明业务。书店和音像店就是零售业的例子。发动机设计专利和苯甲酰亚胺专利是智能照明业务的例子。这两种业务类型完全不相关 投资公司有一个叫做投资回报的概念。它是从每项业务中获得的利润。对于每种“业务类型”(零售、智能照明),投资回报的计算逻辑是不同的 我需要通过计算每个“业务类型”的投资来创建一个投资回报计算器C# 如何使用泛型实现此功能?,c#,oop,generics,design-patterns,dry,C#,Oop,Generics,Design Patterns,Dry,我没有使用.Net泛型的经验。我正在为投资控股公司在.NET4.0中设计一个软件系统。公司拥有零售业务和智能照明业务。书店和音像店就是零售业的例子。发动机设计专利和苯甲酰亚胺专利是智能照明业务的例子。这两种业务类型完全不相关 投资公司有一个叫做投资回报的概念。它是从每项业务中获得的利润。对于每种“业务类型”(零售、智能照明),投资回报的计算逻辑是不同的 我需要通过计算每个“业务类型”的投资来创建一个投资回报计算器 public static class InvestmentReturnCalcu
public static class InvestmentReturnCalculator
{
public static double GetNetInvestementReturn(List<IBusiness> allMyProfitableBusiness, List<InvestmentReturnElement<IBusiness>> profitElements)
{
double totalReturn = 0;
foreach (IBusiness b in allMyProfitableBusiness)
{
//How to do calculation?
}
return totalReturn;
}
}
更新:
书店
,引擎设计专利
继承了不同的基类。因此,我不能将IBusiness
、IRetailBusiness
和IIntellectualRights
作为抽象类。它们应保持为接口
现在@Grzenio建议在每个实体(书店、音像店等)中实施GetInvestmentProfit
方法。在这里,我将重复相同的代码。同样,这不符合DRY
此外,投资回报
概念适用于投资控股公司。个别业务类型不知道这样一个概念
投资回报要素
List<InvestmentReturnElement> profitElements = new List<InvestmentReturnElement>();
var salesProfitBook = new RetailProfit(bookShop1);
var salesProfitAudioCD = new RetailProfit(cd1Shop);
var intellectualProfitEngineDesign = new IntellectualRightsProfit(enginePatent);
var intellectualProfitBenzolMedicine = new IntellectualRightsProfit(medicinePatent);
profitElements.Add(salesProfitBook);
profitElements.Add(salesProfitAudioCD);
profitElements.Add(intellectualProfitEngineDesign);
profitElements.Add(intellectualProfitBenzolMedicine);
foreach (var profitelement in profitElements)
{
Console.WriteLine("Profit: {0:c}", profitelement.GetInvestmentProfit());
}
Console.ReadKey();
具体业务
#region Intellectuals
public class EngineDesignPatent : IIntellectualRights
{
public double Royalty { get; set; }
}
public class BenzolMedicinePatent : IIntellectualRights
{
public double Royalty { get; set; }
}
#endregion
#region Retails
public class BookShop : IRetailBusiness
{
public bool IsOnSale { get; set; }
public double Revenue { get; set; }
}
public class AudioCDShop : IRetailBusiness
{
public bool IsOnSale { get; set; }
public double Revenue { get; set; }
}
#endregion
public class RetailInvestmentReturnCalculator : InvestmentReturnCalculator<IRetailBusiness>
{
public RetailInvestmentReturnCalculator(IRetailBusiness retail)
{
BusinessType = retail;
//Business = new BookShop(100);
}
public override double GetInvestmentProfit()
{
ProfitElement = BusinessType.GrossRevenue;
return CalculateBaseProfit();
}
}
public class IntellectualRightsInvestmentReturnCalculator : InvestmentReturnCalculator<IIntellectualRights>
{
public IntellectualRightsInvestmentReturnCalculator(IIntellectualRights intellectual)
{
BusinessType = intellectual;
}
public override double GetInvestmentProfit()
{
ProfitElement = BusinessType.Royalty;
return base.CalculateBaseProfit();
}
}
public interface IBusiness
{
InvestmentReturnCalculator GetMyInvestmentReturnCalculator();
}
public abstract class EntityBaseClass
{
}
public interface IRetailBusiness : IBusiness
{
double GrossRevenue { get; set; }
}
public interface IIntellectualRights : IBusiness
{
double Royalty { get; set; }
}
public class EngineDesignPatent : EntityBaseClass, IIntellectualRights
{
public double Royalty { get; set; }
public EngineDesignPatent(double royalty)
{
Royalty = royalty;
}
public InvestmentReturnCalculator GetMyInvestmentReturnCalculator()
{
return new IntellectualRightsInvestmentReturnCalculator(this);
}
}
public class BookShop : EntityBaseClass, IRetailBusiness
{
public double GrossRevenue { get; set; }
public BookShop(double grossRevenue)
{
GrossRevenue = grossRevenue;
}
public InvestmentReturnCalculator GetMyInvestmentReturnCalculator()
{
return new RetailInvestmentReturnCalculator(this);
}
}
public class AudioCDShop : EntityBaseClass, IRetailBusiness
{
public double GrossRevenue { get; set; }
public AudioCDShop(double grossRevenue)
{
GrossRevenue = grossRevenue;
}
public InvestmentReturnCalculator GetMyInvestmentReturnCalculator()
{
return new RetailInvestmentReturnCalculator(this);
}
}
客户端
List<InvestmentReturnElement> profitElements = new List<InvestmentReturnElement>();
var salesProfitBook = new RetailProfit(bookShop1);
var salesProfitAudioCD = new RetailProfit(cd1Shop);
var intellectualProfitEngineDesign = new IntellectualRightsProfit(enginePatent);
var intellectualProfitBenzolMedicine = new IntellectualRightsProfit(medicinePatent);
profitElements.Add(salesProfitBook);
profitElements.Add(salesProfitAudioCD);
profitElements.Add(intellectualProfitEngineDesign);
profitElements.Add(intellectualProfitBenzolMedicine);
foreach (var profitelement in profitElements)
{
Console.WriteLine("Profit: {0:c}", profitelement.GetInvestmentProfit());
}
Console.ReadKey();
类程序
{
静态void Main(字符串[]参数)
{
#米布斯地区
List allMyProfitableBusiness=new List();
书店书店1=新书店();
AudioCDShop cd1Shop=新的AudioCDShop();
EngineDesignPatient EnginePart=新的EngineDesignPatient();
苯甲酰亚胺专利药物专利=新苯甲酰亚胺专利();
allMyProfitableBusiness.Add(书店1);
allMyProfitableBusiness.Add(cd1Shop);
allMyProfitableBusiness.Add(EnginePart);
allMyProfitableBusiness.Add(医药专利);
#端区
列表profitElements=新列表();
var salesProfitBook=新零售利润();
var salesProfitAudioCD=新零售利润();
var intellectualProfitEngineDesign=新的IntellectualRightsProfit();
var intellitualprofitbenzolmedicine=新的intellitualrightsprofit();
//profitElements.Add(salesProfitBook);
Console.ReadKey();
}
}
回答您的问题
(1)尝试制作InvestmentReturnElement
逆变(和所有继承人):
选项2:或者您可能会得出这样的结论,即业务与利润计算的角度非常不同,您会将一种类型的列表与另一种类型分开,并在不使用泛型的情况下处理它们。虽然我想不出使用泛型的解决方案,但我相信这正是您想要的:
public abstract class InvestmentReturnElement
{
protected InvestmentReturnElement(IBusiness business)
{
this.Business = business;
}
public IBusiness Business { get; private set; }
public abstract double GetInvestmentProfit();
}
public class RetailProfit : InvestmentReturnElement
{
public RetailProfit(IRetailBusiness retailBusiness)
: base(retailBusiness)
{
}
public override double GetInvestmentProfit()
{
return ((IRetailBusiness)this.Business).Revenue * 5 / 100;
}
}
public class IntellectualRightsProfit : InvestmentReturnElement
{
public IntellectualRightsProfit(IIntellectualRights intellectualRightsBusiness)
: base(intellectualRightsBusiness)
{
}
public override double GetInvestmentProfit()
{
return ((IIntellectualRights)this.Business).Royalty * 10 / 100;
}
}
客户端
List<InvestmentReturnElement> profitElements = new List<InvestmentReturnElement>();
var salesProfitBook = new RetailProfit(bookShop1);
var salesProfitAudioCD = new RetailProfit(cd1Shop);
var intellectualProfitEngineDesign = new IntellectualRightsProfit(enginePatent);
var intellectualProfitBenzolMedicine = new IntellectualRightsProfit(medicinePatent);
profitElements.Add(salesProfitBook);
profitElements.Add(salesProfitAudioCD);
profitElements.Add(intellectualProfitEngineDesign);
profitElements.Add(intellectualProfitBenzolMedicine);
foreach (var profitelement in profitElements)
{
Console.WriteLine("Profit: {0:c}", profitelement.GetInvestmentProfit());
}
Console.ReadKey();
List profitElements=new List();
var salesProfitBook=新零售利润(书店1);
var salesProfitAudioCD=新零售利润(cd1Shop);
var IntellitualProfiteEngineedDesign=新的IntellitualRightsProfit(引擎组件);
var IntellitualProfitbenzolmedicine=新的智能权利协议(医药专利);
profitElements.Add(salesProfitBook);
profitElements.Add(销售profitaudiocd);
profitElements.Add(智能专业设计);
profitElements.Add(智能型苯并美辛);
foreach(profitelement中的var profitelement)
{
WriteLine(“利润:{0:c}”,profitelement.GetInvestmentProfit());
}
Console.ReadKey();
考虑到公式与目标接口相关联,这是最简单的解决方案。以下是基于中@Kit的第一个响应的解决方案 在泛型的帮助下,它避免了任何类型检查 计算器抽象
public abstract class InvestmentReturnCalculator
{
public double ProfitElement { get; set; }
public abstract double GetInvestmentProfit();
protected double CalculateBaseProfit()
{
double profit = 0;
if (ProfitElement < 5)
{
profit = ProfitElement * 5 / 100;
}
else
{
profit = ProfitElement * 10 / 100;
}
return profit;
}
}
public abstract class InvestmentReturnCalculator<T> : InvestmentReturnCalculator where T : IBusiness
{
public T BusinessType { get; set; }
}
具体业务
#region Intellectuals
public class EngineDesignPatent : IIntellectualRights
{
public double Royalty { get; set; }
}
public class BenzolMedicinePatent : IIntellectualRights
{
public double Royalty { get; set; }
}
#endregion
#region Retails
public class BookShop : IRetailBusiness
{
public bool IsOnSale { get; set; }
public double Revenue { get; set; }
}
public class AudioCDShop : IRetailBusiness
{
public bool IsOnSale { get; set; }
public double Revenue { get; set; }
}
#endregion
public class RetailInvestmentReturnCalculator : InvestmentReturnCalculator<IRetailBusiness>
{
public RetailInvestmentReturnCalculator(IRetailBusiness retail)
{
BusinessType = retail;
//Business = new BookShop(100);
}
public override double GetInvestmentProfit()
{
ProfitElement = BusinessType.GrossRevenue;
return CalculateBaseProfit();
}
}
public class IntellectualRightsInvestmentReturnCalculator : InvestmentReturnCalculator<IIntellectualRights>
{
public IntellectualRightsInvestmentReturnCalculator(IIntellectualRights intellectual)
{
BusinessType = intellectual;
}
public override double GetInvestmentProfit()
{
ProfitElement = BusinessType.Royalty;
return base.CalculateBaseProfit();
}
}
public interface IBusiness
{
InvestmentReturnCalculator GetMyInvestmentReturnCalculator();
}
public abstract class EntityBaseClass
{
}
public interface IRetailBusiness : IBusiness
{
double GrossRevenue { get; set; }
}
public interface IIntellectualRights : IBusiness
{
double Royalty { get; set; }
}
public class EngineDesignPatent : EntityBaseClass, IIntellectualRights
{
public double Royalty { get; set; }
public EngineDesignPatent(double royalty)
{
Royalty = royalty;
}
public InvestmentReturnCalculator GetMyInvestmentReturnCalculator()
{
return new IntellectualRightsInvestmentReturnCalculator(this);
}
}
public class BookShop : EntityBaseClass, IRetailBusiness
{
public double GrossRevenue { get; set; }
public BookShop(double grossRevenue)
{
GrossRevenue = grossRevenue;
}
public InvestmentReturnCalculator GetMyInvestmentReturnCalculator()
{
return new RetailInvestmentReturnCalculator(this);
}
}
public class AudioCDShop : EntityBaseClass, IRetailBusiness
{
public double GrossRevenue { get; set; }
public AudioCDShop(double grossRevenue)
{
GrossRevenue = grossRevenue;
}
public InvestmentReturnCalculator GetMyInvestmentReturnCalculator()
{
return new RetailInvestmentReturnCalculator(this);
}
}
客户端
static void Main(string[] args)
{
#region MyBusines
List<IBusiness> allMyProfitableBusiness = new List<IBusiness>();
BookShop bookShop1 = new BookShop(75);
AudioCDShop cd1Shop = new AudioCDShop(80);
EngineDesignPatent enginePatent = new EngineDesignPatent(1200);
BenzolMedicinePatent medicinePatent = new BenzolMedicinePatent(1450);
allMyProfitableBusiness.Add(bookShop1);
allMyProfitableBusiness.Add(cd1Shop);
allMyProfitableBusiness.Add(enginePatent);
allMyProfitableBusiness.Add(medicinePatent);
#endregion
var investmentReturns = allMyProfitableBusiness.Select(bus => bus.GetMyInvestmentReturnCalculator()).ToList();
double totalProfit = 0;
foreach (var profitelement in investmentReturns)
{
totalProfit = totalProfit + profitelement.GetInvestmentProfit();
Console.WriteLine("Profit: {0:c}", profitelement.GetInvestmentProfit());
}
Console.ReadKey();
}
static void Main(字符串[]args)
{
#米布斯地区
List allMyProfitableBusiness=new List();
书店书店1=新书店(75);
AudioCD商店cd1Shop=新的AudioCD商店(80);
EngineedDesignPatient EngineePart=新的EngineedDesignPatient(1200);
苯甲二烯类药物专利=新苯甲二烯类药物专利(1450);
allMyProfitableBusiness.Add(书店1);
allMyProfitableBusiness.Add(cd1Shop);
allMyProfitableBusiness.Add(EnginePart);
allMyProfitableBusiness.Add(医药专利);
#端区
var investmentReturns=allMyProfitableBusiness.Select(总线=>bus.GetMyInvestmentReturnCalculator()).ToList();
双倍总利润=0;
foreach(投资回报中的var利润)
{
totalProfit=totalProfit+profitelement.GetInvestmentProfit();
WriteLine(“利润:{0:c}”,profitelement.GetInvestmentProfit());
}
Console.ReadKey();
}
要按现在的方式实现此功能,您需要使用反射来确定类型并调用正确的方法。更好的解决方案是使用GetProfit这样的方法创建一个公共接口,并使您的每个业务对象继承此接口,并在每个业务中实现您需要的GetProfit。同样,这不是令人满意的干燥。我不同意这一点。如果每个实体的公式都不同(即使只是稍微不同),那么您的设计仍然是枯燥的。Eric Lippert的博客帮助中会出现类似的内容吗?出现编译错误:无效的方差修饰符。只能将接口和委托类型参数指定为变量。