如何避免冗余代码没有不必要的泛型泛型

时间:2014-02-06 10:06:19

标签: c# generics

在问题“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();
    }

参考

  1. C# generics: cast generic type to value type
  2. Refactoring Code to avoid Type Casting
  3. Refactoring class design to convey the design intention

0 个答案:

没有答案