将数据传递给Method的更好方法是哪种

时间:2015-07-29 08:40:18

标签: c# .net oop parameter-passing

我们假设我们有两个类Expense1Expense2。哪个类实现比另一个更受欢迎,或者被认为更接近于面向对象?

我一直认为做Exp2.Calculate(1.5M,2)比读取更可读 exp1.Calculate()并使用exp1 Class的属性作为calculate方法的必需值。

Expense1

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;
    }
}

Expense2

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

两个类的实施

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();
    }
}

4 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

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

Expense1是具有非线程安全状态的经典OOP训练 - 并且不保证Result将返回线程调用Calculate的结果。此外,阅读和维护很冗长,也很复杂。

我每次都赞成Expense2超过Expense1。我唯一要做的就是让它变得静态,因为必须创建一个Expense2的实例才能调用Calculate

答案 2 :(得分:1)

我不喜欢Expense1一点。我认为通常应该避免使用public get / set的属性,因为它不提供封装。它甚至不比公共场地更好(虽然它确实为后面的防守条款提供了一些空间)。

然而,更糟糕的是,Calculate()方法是imo。它不需要参数,但它仍然会改变对象的内部状态。目前尚不清楚如何。同时,它写入的字段result不会被属性Result返回,该属性再次执行相同的计算(如果必须进行计算,通常更喜欢方法在一处房产上。)

最后,没有必要在构造函数中将基元类型初始化为其默认值,数字类型始终初始化为0.

===

Expense2更好,更清楚发生了什么。 Method采用两个名称齐全的参数,并立即给出合理的结果。

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

答案 3 :(得分:1)

这一切都取决于你想做什么,但经验法则是当它们真正链接到对象时使用属性,并在它们位于对象外部时将需要的用途传递给参数。

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

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

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

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