我如何避免遍历相同数据

时间:2019-07-08 05:56:39

标签: c# loops for-loop datatable

TB_COST.Data是我的DataTable,我正在遍历数据并计算一些字段。我想为每个计算使用单独的函数,但是我反复循环数据。我正在寻找避免重复的方法。

我试图循环一次数据并在内部调用函数,但是我认为以后很难修正错误。

    public void CalculateCost()//this function getting called at a button onclick
    {
        try
        {
            CalculateProductPrice();
            CalculateFreight();            
        }
        catch(Exception ex)
        {
            ShowMessageBox(ex.ToString());
        }
    }

    public void CalculateProductPrice()
    {
        decimal totalTonage = Convert.ToDecimal("0");
        decimal totalPrice = Convert.ToDecimal("0");
        decimal priceCarpiTonage = Convert.ToDecimal("0");
        for(int i = 0; i < TB_COST.Data.Rows.Count; i++)
        {
            decimal containerTonage = Convert.ToDecimal(TB_COST.Data.Rows[i]["CONTON"].ToString());
            totalTonage += containerTonage;
            decimal price = Convert.ToDecimal(TB_COST.Data.Rows[i]["PROPRI"].ToString());
            totalPrice += price;
            priceCarpiTonage +=  Convert.ToDecimal(containerTonage) * price; 
        }
        decimal productPrice = priceCarpiTonage/totalTonage;
        productPrice = (Math.Round(productPrice, 2, MidpointRounding.AwayFromZero));
        //ShowMessageBox(totalPrice + " " + priceCarpiTonage + " " + productPrice);
        T_PROP.Text = productPrice.ToString();
        T_TOTN.Text = totalTonage.ToString();                     
    }
    public void CalculateFreight()
    {
        decimal totalFreight = Convert.ToDecimal("0");
        for(int i = 0; i < TB_COST.Data.Rows.Count; i++)
        {
            decimal decimalFreightPrice = Convert.ToDecimal(TB_COST.Data.Rows[i]["CONPRI"].ToString());
            decimal containerTonnage = Convert.ToDecimal(TB_COST.Data.Rows[i]["CONTON"].ToString());
            decimal decimalFreightBoluContainerTonnage = decimalFreightPrice/containerTonnage;
            totalFreight += decimalFreightBoluContainerTonnage;                
        }
        //ShowMessageBox(totalFreight.ToString());
        totalFreight = (Math.Round(totalFreight, 2, MidpointRounding.AwayFromZero));                                  
        T_FREG.Text = totalFreight.ToString();
    }

2 个答案:

答案 0 :(得分:1)

根据您的评论和mr springers's answer,我认为您只需要添加一些辅助函数并在for中调用它们即可。

注意:要使其可以进行单元测试,需要一些有关TB_COST的信息。那么签名将为public CalculationsResult PerformCalculations(???? TB_COST),并且不会与UI交互。

public void PerformCalculations()//this function getting called at a button onclick
{
    try
    {
        CalculationsResult calculations = new CalculationsResult();

        for(int i = 0; i < TB_COST.Data.Rows.Count; i++)
        {
            DoMyCalculation(calculations, TB_COST.Data.Rows[i]);
            // Call other calculations
        }
        decimal productPrice = calculations.PriceCarpiTonage / calculations.TotalTonage;
        productPrice = (Math.Round(productPrice, 2, MidpointRounding.AwayFromZero));
        T_PROP.Text = productPrice.ToString();
        T_TOTN.Text = totalTonage.ToString();   


        totalFreight = (Math.Round(totalFreight, 2, MidpointRounding.AwayFromZero));                                  
        T_FREG.Text = totalFreight.ToString();         
    }
    catch(Exception ex)
    {
        ShowMessageBox(ex.ToString());
    }
}

private void DoMyCalculation(CalculationsResult calculations, DataRow row)
{
    calculations.TotalPrice += (decimal)row["MyColumn"];
}

public class CalculationsResult 
{
    public decimal TotalTonage { get; set; }
    public decimal TotalPrice { get; set; }
    public decimal PriceCarpiTonage { get; set; }
}

答案 1 :(得分:0)

最简单的方法是将两个方法合并为一个大方法:

此后,您会遇到方法太大而难以维护的问题。因此,您必须再次重构此方法。

您现在应该更改此方法,以遵守可靠的原则。 https://medium.com/@mirzafarrukh13/solid-design-principles-c-de157c500425

第一步,您应该创建一个新对象,该对象代表数据表的一行。之后,您应该创建一个新方法来将数据从数据表加载到该对象的列表中。

public class TbCost {
    public decimal Conton {get;set;}
    public decimal ProPri {get;set;}
    public decimal ConPri {get;set;}

    public decimal GetPriceCarpiTonage() {
        return Conton * ProPri;
    }

    public decimal GetFreightBoluContainerTonnage() {
        return ConPri / Conton;
    }
}

public void CalculateCost()//this function getting called at a button onclick
{
    try
    {
        decimal totalTonage = 0m;
        decimal totalPrice = 0m;
        decimal priceCarpiTonage = 0m;
        decimal totalFreight = 0m;

        IList<TbCost> tbCosts = ReadTbCosts(TB_COST.Data.Rows);

        foreach (TbCost tbCost in tbCosts)
        {
            totalTonage += tbCost.Conton;               
            totalPrice += tbCost.ProPri;
            priceCarpiTonage +=  tbCost.GetPriceCarpiTonage(); 
            totalFreight += tbCost.GetFreightBoluContainerTonnage();   
        }

        T_PROP.Text = Round(priceCarpiTonage/totalTonage);
        T_TOTN.Text = totalTonage.ToString();                                
        T_FREG.Text = Round(totalFreight);
    }
    catch(Exception ex)
    {
        ShowMessageBox(ex.ToString());
    }
}

// This method should be moved to a sperate class
private string Round(decimal decimalValue) {
    return (Math.Round(decimalValue, 2, MidpointRounding.AwayFromZero)).ToString();
}