Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.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#_.net_Oop_Parameter Passing - Fatal编程技术网

C# 将数据传递给方法的更好方法是什么

C# 将数据传递给方法的更好方法是什么,c#,.net,oop,parameter-passing,C#,.net,Oop,Parameter Passing,假设我们有两类Expense1和Expense2。哪个类实现优于其他类实现,或者哪个类更接近于面向对象 我一直认为做Exp2.Calculate(1.5M,2)比 exp1.Calculate()并使用exp1类的属性作为计算方法所需的值 费用1 using System; using System.Collections.Generic; using System.Linq; using System.Text; public class Expense1 { public deci

假设我们有两类
Expense1
Expense2
。哪个类实现优于其他类实现,或者哪个类更接近于面向对象

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

费用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;
    }
}
两个类的实现

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

这将允许
费用
的内部状态在对象的生命周期内保持一致,并定义如何计算
费用。2.Calculate
是确定性的(每次使用相同的参数调用它时都有相同的结果),因为它没有副作用(参数提供给它,而不是通过属性)它也是线程安全的。最后,它更简单,更容易阅读

Expense1
是一个典型的OOP火车故障,具有非线程安全状态,并且不能保证
Result
将返回线程调用
Calculate
的结果。此外,它的读取和维护非常繁琐


每次我都喜欢
Expense2
而不是
Expense1
。我唯一要改变的是使其保持静态,因为调用
Calculate

调用
Expense2
没有任何好处。我一点都不喜欢Expense1。我认为公共get/set属性通常应该避免,因为它是不提供封装。它几乎不比公共字段更好(尽管它确实为将来的保护条款等提供了一些空间)

然而,比这更糟糕的是Calculate()方法imo。它不接受任何参数,但仍会更改对象的内部状态。不清楚如何更改。同时,它写入的字段,
result
,不会由属性
result
返回,该属性再次执行相同的计算(如果必须进行计算,通常会选择方法而不是属性)

最后,无需在构造函数中将基元类型初始化为其默认值,数字类型总是初始化为0

===

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


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

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

一个简单的例子,考虑把人作为一个类,它的一个属性是生日,所以在这种情况下你应该做这个< /P>

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

如果您只需要
Calculate
方法中的
NumberOfItems
ExpenseValue
值,则使用
Expense2
。如果您在
Expense
类中的其他地方使用它们,则使用
Expense
\
Expense1
有利于数据绑定。
Expense2
有利于服务calls。就各自的用途而言,两者都是很好的OOP。@阿塔拉瓦蒂,我完全不同意。阅读答案,你会发现它们根本不属于“几乎完全基于观点,而不是事实、参考或特定专业知识”的范畴.@ataravati我同意David的观点,因为这不是基于意见的。有足够经验的程序员应该知道哪种方法随着时间的推移更易于维护,并被视为最佳实践。@ataravati,选择上述任何一种方法都可能对正在开发的应用程序产生严重影响。因此,这对于OP-an非常重要d所有认为以上是基于意见的决定的人都应该改变他们的想法,并研究每种方法的考虑因素和后果。我相信好的答案和代码片段将有助于使这篇文章成为一篇有价值和有教育意义的文章,所以我将标记它重新开放。不过,我强烈反对让生日像这样易变。生日不会改变(只要我们关注良好的OOP实践;)@kai将Person视为使用EntityFramework从数据库加载的模型,这是一个超出问题范围的细节:)@Swift,我不想在这里争论,这正是业务逻辑代码不应该直接与实体一起工作的原因。更好的方法是生成一个合适的业务对象,它只允许编写可更新的成员。这也是以良好的OOP设计的名义。我不会使用实体特定的问题来证明设计缺陷的合理性。因此,在这种情况下,某个类中的方法不应使用该类的属性,那么某个类的哪些属性仅用于状态检查?@nayefharb,我建议遵循以下简单规则:如果可以避免类中的字段,请这样做。如果必须有一个字段,请尝试将其设置为只读,不要直接公开它。如果必须公开,请尝试仅提供