【问题标题】:Getter, Function or just set it on constructor?Getter、Function 还是仅在构造函数上设置它?
【发布时间】:2013-09-01 09:09:52
【问题描述】:

我找不到在类中编写一些计算的良好性能和易读性的方法。 想象一下下面的类和所有获取 FinalPrice 的方法:

public class Order {
    public Order(Product[] products) {
        Items = products;

选项 1:为每个要计算的属性声明一个变量,可读性极差


        var orderPrice = products.Sum(p => p.Price * p.Quantity);
        var orderTaxes = products.Sum(p => p.Taxes * p.Quantity);
        var orderDiscount = products.Sum(p => p.Price * p.Quantity * p.Discount);

        OrderPrice = orderPrice;
        OrderTaxes = orderTaxes;
        OrderDiscount = orderDiscount;

        FinalPrice = orderPrice + orderTaxes - orderDiscount;

选项2:课堂顺序问题很重要! FinalPrice 行不能在其他行之前,否则它将不起作用但不会引发错误。


        OrderPrice = products.Sum(p => p.Price * p.Quantity);
        OrderTaxes = products.Sum(p => p.Taxes * p.Quantity);
        OrderDiscount = products.Sum(p=> p.Price * p.Quantity * p.Discount);

        FinalPrice = OrderPrice + OrderTaxes - OrderDiscount;

选项 3:重写所有公式 - 不利于维护。最有可能在以后引入价格差异。


        FinalPrice = products.Sum(p => p.Price * p.Quantity) + 
                     products.Sum(p => p.Taxes * p.Quantity) - 
                     products.Sum(p => p.Price * p.Quantity * p.Discount);

    }

选项 4:使用吸气剂。这将在每次调用时计算。这是一个简单的计算,但假设代码更多。


    public decimal FinalPrice { get {
        return OrderPrice + OrderTaxes - OrderDiscount;
    } }
}

选项 5:使用函数。这是好事还是坏事??


    public decimal CalculateFinalPrice() {
        return OrderPrice + OrderTaxes - OrderDiscount;
    }

【问题讨论】:

    标签: c# coding-style code-structure


    【解决方案1】:

    我会在 getter 中完成所有逻辑:

    public decimal CalculateFinalPrice
    {
        get { return CalculateOrderPrice + CalculateOrderTaxes - CalculateOrderDiscount; }
    }
    
    public decimal CalculateOrderPrice
    {
        get { return products.Sum(p => p.Price*p.Quantity); }
    }
    
    public decimal CalculateOrderTaxes
    {
        get { return products.Sum(p => p.Taxes*p.Quantity); }
    }
    
    public decimal CalculateOrderDiscount
    {
        get { return products.Sum(p => p.Price*p.Quantity*p.Discount); }
    }
    

    如果这在您的情况下很慢,您可以缓存属性。

    private decimal? _calculateOrderPrice;
    public decimal CalculateOrderPrice
    {
        get
        {
            if (_calculateOrderPrice == null)
            {
                _calculateOrderPrice = products.Sum(p => p.Price*p.Quantity;
            }
            return _calculateOrderPrice.Value;
        }
    }
    

    如果您转到属性的定义,您可以立即看到它是如何计算的。你也不关心需要先完成哪些计算。

    【讨论】:

    • 你能在缓存场景中添加一些东西吗?您的意思是将值存储在私有属性上?使用 getter 代替函数还有什么好处?
    • @Bart。是的,您可以使用 Lazy 将缓存存储在私有字段中。何时使用属性或何时使用不带参数的函数。这是一个很长的故事。现在我应该说,如果 vanlue 永远不会改变,并且如果您第一次使用该属性不是很慢,但是,您可以使用(缓存)属性。
    • @AlexSiepman 附注。缓存很好。但是,如果任何人更改了Order 对象的状态,您需要确保使缓存无效(如果Order 类是可变的,这在此示例中似乎不是。一旦Order 对象被实例化为Product数组,我猜没有客户端会更改数组。)
    • @Imran 使用缓存的方式取决于上下文和代码指南。我不会更改传入的参数,但也许其他人会这样做。有时最好使用不可变对象或创建一个克隆,以使其无法更改传入的值。我可以添加所有场景,但答案会变得很长。
    • @AlexSiepman 是的,我同意。缓存不是 OP 所要求的。这就是我提到它只是旁注的原因。
    【解决方案2】:

    我将为CalculateFinalPriceCalculateOrderPriceCalculateOrderTaxesCalculateOrderDiscount 创建方法,如下所示:

    public decimal CalculateFinalPrice() {
        return CalculateOrderPrice() + CalculateOrderTaxes() - CalculateOrderDiscount();
    }
    
    public decimal CalculateOrderPrice()
    {
        // Logic here to calculate order price
        return theOrderPrice;
    }
    
    public decimal CalculateOrderTaxes()
    {
        // Logic here to calculate order taxes
        return theOrderTaxes;
    }
    
    public decimal CalculateOrderDiscount()
    {
        // Logic here to calcuate order discount
        return theOrderDiscount;
    }
    

    这为您提供了更多但更小的部分,更易于维护、阅读和单元测试,因为每个方法都有一个单一的职责。

    【讨论】:

    • 关于为什么使用 Functions 而不是 Getters 的任何信息?只是想知道为什么你更喜欢函数方法而不是建议 getter 方法的 Alex
    • 我更喜欢方法方法,因为方法可能附加到实例,也可能不附加,而属性必然是类实例的一部分。例如,您可以使上述方法成为实用程序类的一部分,其中所有方法都是静态的,并且它们可以被应用程序的其他部分使用,而无需知道对象的任何特定实例。
    • @Bart 以下是关于属性与方法的 SO 问题的一些很好的解释。 link1, link2
    • 接受了另一个答案,因为我认为 getter / setter 更适合我的情况。你的答案仍然和另一个一样好。不幸的是,我不能接受两个答案。
    • @Bart - 不用担心,只要你得到你想要的帮助,这才是最重要的。祝你好运。
    猜你喜欢
    • 1970-01-01
    • 2018-08-08
    • 2011-01-09
    • 2023-02-06
    • 2011-03-26
    • 2010-10-24
    • 1970-01-01
    • 2013-07-30
    • 2011-07-10
    相关资源
    最近更新 更多