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

C# 使用整个类作为参数-良好实践?

C# 使用整个类作为参数-良好实践?,c#,class,parameters,C#,Class,Parameters,假设一个名为“Place”的类存储位置和相关细节: class Place { string Name; string Location; // etc... } 稍后,我们将填充多达80个不同城镇的名称和详细信息。因此,我们将这些城镇以数字形式存储在一个数组中: class Setup { public static GetTowns { for (int i = 1; i <= numberOfTowns; i++)

假设一个名为“Place”的类存储位置和相关细节:

class Place
{
    string Name;
    string Location;
    // etc...
}
稍后,我们将填充多达80个不同城镇的名称和详细信息。因此,我们将这些城镇以数字形式存储在一个数组中:

class Setup
{
    public static GetTowns
    {
        for (int i = 1; i <= numberOfTowns; i++)
        {
            Town[i] = new Place(name, location);
        }
        // more code...
    }
    // more methods...
}
其他方法需要访问多个城镇或所有城镇。然后我们可以将整个Town数组作为参数传入:

public static void ListAllTowns(Place[] Town)
{
    Console.WriteLine("Our Beloved Clients:");
    foreach (Place here in Town)
    {
        Console.WriteLine("{0} in {1}", here.Name, here.Location);
        // Various other operations requiring info about the Towns
    }
}
完整的参考文献C#2.0陈述了以下内容

参数是在调用方法时接收传入方法的参数值的变量

这似乎意味着一个类的每个实例以及所有涉及的数据在每次调用时都会被传递到
ListAllTowns
。对我来说这听起来很浪费,但这是真的吗


(由于概念验证的原因,这个例子被大大简化了,但是方法需要读/写权限和多个城镇之间的比较。)

它没有任何浪费。您没有传递所有项目的副本,您只是创建了一个数组,然后将对该数组的引用传递给
ListAllTowns
方法(数组是引用类型)


您正在以正确的方式进行操作。

参数始终按值传递(除非使用
ref
out
关键字),但对于引用类型,值不是对象本身,而是对对象的引用

因此,整个对象不是作为参数传递的,只是对对象的引用。

默认情况下,C#中的所有类都是引用,因此只有一个指针被发送到函数

回答你的问题:视情况而定。有时,将整个对象作为参数发送确实是有意义的(即,我们正在尝试使用对象发送某些内容)。另一方面,仅为函数参数创建类可能并不好。在您的特定示例中,创建一个类是有意义的


我刚才所说的有一个例外:结构作为副本发送(所有成员都将被复制)。在将这些作为函数参数发送时必须小心。

在.NET中,对象作为引用保留。在本例中,您不是传递或复制整个数据,而是引用已创建的该数据实例


在这种情况下,我们鼓励传递整个实例,因为它允许您保持一致性(处理Towns的方法将Towns作为参数获取是有意义的)

我的观点是,将类作为参数传递是完全正确的。这得到了包括Robert Martins Clean Code在内的许多作者的支持。我还认为,您应该尽可能避免传递参数。如果不将Town对象数组传递给ListAllTowns方法,而是将“ListAll”设置为Place类的方法,那么您将如下调用该方法:

Towns.ListAll()


从这个意义上讲,您不必在每次使用该列表时都将其传递给函数,因为它只需对其拥有的对象进行操作。

这总是一个难题

一方面,Occam的剃刀说你不需要任何多余的东西,另一方面,将
DescribeTown(PlaceTown)
更改为
DescribeTown(string TownName)
意味着不采用OOP方式,而这反过来意味着未来代码将更难更改和维护

但有时当系统成熟和稳定时,当整个
城镇
仍然过剩时,您可以将其重构回
descripbetown(string towname)


还有一个方面——单元测试。测试
DescribeTown(string TownName)
方法比
DescribeTown(Place Town)
更容易,后者需要模拟一个Town对象,并且不清楚应该模拟什么属性(测试之前必须知道它)。

最好选择一本稍新的书来学习。C#2.0在这一点上相当陈旧。虽然这没有错,或者特别糟糕,但如果它使用C#2.0中不可用的较新构造(即,参数作为
IEnumerable
在这里更好),可能会更好。当你超越基础时,差异只会变得更加深刻。请记住,仅仅因为一本书使用了更新版本的语言并不意味着它更高级,也不意味着它不需要花费太多(或更多)的时间来涵盖介绍性主题。还有一些关于C#2.0的高级书籍。)TownsListAll只是一个10秒的演示,表明需要进入所有城镇。在实际的程序中,还有很多事情要做。尽管我会把你的建议放在心上,看看我能在哪里减少参数化的需要。然后你已经在
Towns
上创建了一个硬依赖,这必须在单元测试中模拟出来。让该方法获取参数要好得多。
public static void ListAllTowns(Place[] Town)
{
    Console.WriteLine("Our Beloved Clients:");
    foreach (Place here in Town)
    {
        Console.WriteLine("{0} in {1}", here.Name, here.Location);
        // Various other operations requiring info about the Towns
    }
}