在问题“C# generics: cast generic type to value type”中,Eric Lippert和Jon Skeet都表示以下方法不是一个好的解决方案
//return new T { BusinessType = (U)(object)this }; //Eric Lippert answer (Not suggested)
//return new T { BusinessType = (dynamic)this }; //Jon Skeet answer (Not suggested)
我的C#.Net 4.0解决方案中存在code redundancy
问题。 GetCalculator()
和EngineDesignPatent
都重复了BenzolMedicinePatent
方法。
public override InvestmentReturnCalculator GetCalculator()
{
IntellectualRightsInvestmentReturnCalculator c = new IntellectualRightsInvestmentReturnCalculator();
c.BusinessType = this;
return c;
}
虽然不可取,但@Kit提到了以下方法来避免“Refactoring Code to avoid Type Casting”中的冗余。
//BusinessBaseClass
public abstract class BusinessBaseClass<T, U> : EntityBaseClass, IBusiness
where T : InvestmentReturnCalculator<U>, new()
where U : IBusiness
{
public virtual InvestmentReturnCalculator GetCalculator()
{
//return new T { BusinessType = (U)(object)this }; //Eric Lippert answer (Not suggested)
return new T { BusinessType = (dynamic)this }; //Jon Skeet answer (Not suggested)
}
}
问题
如果没有双重投射方法,避免代码冗余的替代方法是什么?
CODE
商家类型抽象
public interface IBusiness
{
InvestmentReturnCalculator GetCalculator();
}
public interface IRetailBusiness : IBusiness
{
double GrossRevenue { get; set; }
}
public interface IIntellectualRights : IBusiness
{
double Royalty { get; set; }
}
public abstract class EntityBaseClass
{
}
计算器
public abstract class InvestmentReturnCalculator
{
public abstract double ProfitElement { get; }
public double GetInvestmentProfit()
{
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; }
}
public class RetailInvestmentReturnCalculator : InvestmentReturnCalculator<IRetailBusiness>
{
public override double ProfitElement { get { return BusinessType.GrossRevenue; } }
}
public class IntellectualRightsInvestmentReturnCalculator : InvestmentReturnCalculator<IIntellectualRights>
{
public override double ProfitElement { get { return BusinessType.Royalty; } }
}
具体业务类型参与
public class EngineDesignPatent : BusinessBaseClass<IntellectualRightsInvestmentReturnCalculator, IIntellectualRights>, IIntellectualRights
{
public double Royalty { get; set; }
public EngineDesignPatent(double royalty)
{
Royalty = royalty;
}
//public override InvestmentReturnCalculator GetCalculator()
//{
// IntellectualRightsInvestmentReturnCalculator c = new IntellectualRightsInvestmentReturnCalculator();
// c.BusinessType = this;
// return c;
//}
}
public class BenzolMedicinePatent : BusinessBaseClass<IntellectualRightsInvestmentReturnCalculator, IIntellectualRights>, IIntellectualRights
{
public double Royalty { get; set; }
public BenzolMedicinePatent(double royalty)
{
Royalty = royalty;
}
//public override InvestmentReturnCalculator GetCalculator()
//{
// IntellectualRightsInvestmentReturnCalculator c = new IntellectualRightsInvestmentReturnCalculator();
// c.BusinessType = this;
// return c;
//}
}
public class BookShop : BusinessBaseClass<RetailInvestmentReturnCalculator, IRetailBusiness>, IRetailBusiness
{
public double GrossRevenue { get; set; }
public BookShop(double grossRevenue)
{
GrossRevenue = grossRevenue;
}
//public override InvestmentReturnCalculator GetCalculator()
//{
// RetailInvestmentReturnCalculator c = new RetailInvestmentReturnCalculator();
// c.BusinessType = this;
// return c;
//}
}
客户
static void Main(string[] args)
{
#region MyBusines
List<IBusiness> allMyProfitableBusiness = new List<IBusiness>();
BookShop bookShop1 = new BookShop(75);
EngineDesignPatent enginePatent = new EngineDesignPatent(1200);
BenzolMedicinePatent medicinePatent = new BenzolMedicinePatent(1450);
allMyProfitableBusiness.Add(bookShop1);
allMyProfitableBusiness.Add(enginePatent);
allMyProfitableBusiness.Add(medicinePatent);
#endregion
var investmentReturns = allMyProfitableBusiness.Select(bus => bus.GetCalculator()).ToList();
double totalProfit = 0;
foreach (var profitelement in investmentReturns)
{
totalProfit = totalProfit + profitelement.GetInvestmentProfit();
Console.WriteLine("Profit: {0:c}", profitelement.GetInvestmentProfit());
}
Console.ReadKey();
}
参考