Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用泛型实现此功能?_C#_Oop_Generics_Design Patterns_Dry - Fatal编程技术网

C# 如何使用泛型实现此功能?

C# 如何使用泛型实现此功能?,c#,oop,generics,design-patterns,dry,C#,Oop,Generics,Design Patterns,Dry,我没有使用.Net泛型的经验。我正在为投资控股公司在.NET4.0中设计一个软件系统。公司拥有零售业务和智能照明业务。书店和音像店就是零售业的例子。发动机设计专利和苯甲酰亚胺专利是智能照明业务的例子。这两种业务类型完全不相关 投资公司有一个叫做投资回报的概念。它是从每项业务中获得的利润。对于每种“业务类型”(零售、智能照明),投资回报的计算逻辑是不同的 我需要通过计算每个“业务类型”的投资来创建一个投资回报计算器 public static class InvestmentReturnCalcu

我没有使用.Net泛型的经验。我正在为投资控股公司在.NET4.0中设计一个软件系统。公司拥有零售业务和智能照明业务。书店和音像店就是零售业的例子。发动机设计专利和苯甲酰亚胺专利是智能照明业务的例子。这两种业务类型完全不相关

投资公司有一个叫做投资回报的概念。它是从每项业务中获得的利润。对于每种“业务类型”(零售、智能照明),投资回报的计算逻辑是不同的

我需要通过计算每个“业务类型”的投资来创建一个投资回报计算器

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的博客帮助中会出现类似的内容吗?出现编译错误:
无效的方差修饰符。只能将接口和委托类型参数指定为变量。