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

时间:2012-08-21 16:08:00

标签: c# class parameters

假设一个名为“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...
}

要访问特定城镇及其数据,我们将城镇本身作为参数传递并接收:

public static void DescribeTown(Place Town)
{
    // example method from some other class
    Console.WriteLine("Shipping to {0}.", Town.Name);
}

其他方法需要访问多个城镇或所有城镇。然后我们可以将整个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。这对我来说听起来很浪费,但不是吗?

(出于概念验证的原因,此示例严重简化,但方法需要读/写权限以及多个城镇之间的比较。)

6 个答案:

答案 0 :(得分:7)

没有什么可以浪费的。你没有传递所有项目的副本,你只是创建一个数组,然后将对该数组的引用传递给ListAllTowns方法(数组是引用类型)。

你正在以正确的方式做事(其中之一)。

答案 1 :(得分:4)

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

因此,整个对象不作为参数传递,只传递给对象。

答案 2 :(得分:2)

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

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

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

这总是一个两难的问题。

一方面 - 奥卡姆的剃刀说你不需要任何过多的东西 - 在DescribeTown(Place Town)改为DescribeTown(string TownName)意味着不是以OOP方式进行,反过来意味着这就是代码将来很难改变和维持。

但有时当系统成熟且稳定且事实证明整个Town仍然过多时,您可以将其重构为DescribeTown(string TownName)

还有一个方面 - 单元测试。比DescribeTown(string TownName)更容易测试DescribeTown(Place Town)方法,后者需要模拟Town对象,而且你应该模拟哪些属性并不明显(在测试之前你必须知道它)。

答案 5 :(得分:0)

我的观点是,将一个类作为参数传递是完全正确的。这是由罗伯特马丁斯清洁代码等各种作者提供支持。我也相信你应该尽可能避免传递参数。如果不是将一个Town对象数组传递给ListAllTowns方法,而是将“ListAll”作为Place类的方法,那么你可以调用这样的方法:

Towns.ListAll()

从这个意义上说,每次使用它时都不必将列表传递给函数,因为它只是在它自己的对象上运行。