这是将数据传递给方法的更好方法

Which is the better way of passing data to a Method

假设我们有 2 Classes Expense1Expense2。哪个 class 实现优于另一个,或者哪个被认为更接近面向对象?

我一直认为 Exp2.Calculate(1.5M,2)exp1.Calculate() 并使用 exp1 Class 的属性作为计算方法所需的值。

费用1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Expense1
{
    public decimal ExpenseValue { get; set; }
    public int NumberOfItems { get; set; }
    private decimal result;

    public decimal Result
    {
        get
        {
            return this.NumberOfItems * this.ExpenseValue;
        }
    }

    public void Calculate()
    {
        this.result = this.ExpenseValue * this.NumberOfItems;
    }

    public void expense1()
    {
        this.ExpenseValue = 0;
        this.NumberOfItems = 0;
    }
}

费用2

class Expense2
{
    public decimal Calculate(decimal expenseValue, int numberOfItems)
    {
        return expenseValue * numberOfItems;
    }
}

两个classes

的实现
class Program
{
    static void Main(string[] args)
    {

        Expense1 exp1 = new Expense1();
        exp1.NumberOfItems = 2;
        exp1.ExpenseValue = 1.5M ;
        exp1.Calculate();
        Console.WriteLine("Expense1:" + exp1.Result.ToString());

        Expense2 exp2 = new Expense2();
        string result = string.Empty;
        result = exp2.Calculate(1.5M,2).ToString();
        Console.WriteLine("Expense2:" + result);
        Console.ReadKey();
    }
}

Expense2 更容易阅读和理解发生了什么,因为从调用中可以明显看出使用了哪些参数。

Expense1 可能会产生各种副作用,因为调用者可能会忘记在调用 Calculate() 之前设置用于计算的变量。

如果您需要访问用于稍后计算结果的值,您可以使用类似这样的东西

public class Expense {
    public decimal ExpenseValue { get; private set; }
    public int NumberOfItems { get; private set; }
    public decimal Result { get; private set; }


    public decimal Calculate(decimal expenseValue, int numberOfItems) {
        ExpenseValue = expenseValue;
        NumberOfItems = numberOfItems;
        Result = ExpenseValue * NumberOfItems;

        return Result;
    }

    public Expense() {
        Calculate(0, 0);
    }
}

这将允许 Expense 的内部状态在对象的生命周期内保持一致,并定义它是如何 Calculated

Expense2.Calculate 是确定性的(每次使用相同的参数调用时都有相同的结果)并且因为它没有副作用(参数是为它提供的,而不是通过属性)它是线程-也很安全。最后,它更简单易读。

Expense1 是一个经典的 OOP train-wreck,具有非线程安全状态,并且不能保证 Result 将 return 线程调用 [=13= 的结果].此外,阅读和维护起来冗长且复杂。

我每次都喜欢 Expense2 而不是 Expense1。我唯一要改变的是让它成为静态的,因为必须创建一个 Expense2 的实例来调用 Calculate.

没有任何好处

我有点不喜欢 Expense1。我认为通常应该避免使用 public get/set 的属性,因为它不提供封装。它几乎不比 public 字段好(尽管它确实为以后的保护条款等提供了一些空间)。

然而,比这更糟糕的是 Calculate() 方法 imo。它不接受任何参数,但它仍然会改变对象的内部状态。目前尚不清楚如何。同时,它写入的字段 result 未被 属性 Result 返回,属性 再次执行相同的计算(如果您有进行计算,通常更喜欢方法而不是 属性).

最后,没有必要在构造函数中将基本类型初始化为其默认值,数字类型总是初始化为 0。

===

Expense2更好,更清楚发生了什么。方法采用两个命名良好的参数并立即给出合理的结果。

但是,如果此方法是 class 的唯一用例,我会考虑重命名它,因为它不代表费用,它代表接近费用计算器的东西。

这完全取决于你想做什么,但经验法则是当它们真正链接到对象时使用属性,当它们在对象外部时将使用需要作为参数传递。

一个简单的例子,考虑将 Person 作为 class,它的一个属性是生日,所以在这种情况下你应该这样做

public class Person{
     public DateTime Birthday{get;set;}
     public int GetAge(){
          //some implementation
     }
}

另一个例子,考虑有一个立方体对象,在这个立方体对象中你有一个与另一个立方体相交的方法,在这种情况下你应该将第二个立方体作为参数传递而不是使它成为 属性多维数据集,因为它是外部的东西。

public class Cube{
     public Cube Intersect(Cube other){
         //Do your logic here
     }
}