如何最好地修改和返回C#参数?

时间:2011-09-22 15:50:39

标签: c# return-type signatures

我需要一个已经设置了几个属性值的Widget。我需要更改Widget的名称。我被选为第3选项,但我很难说清楚原因。

public void Do(Widget widget) { // 1
    widget.Name = "new name";
}

public void Do(ref Widget widget) { // 2
    widget.Name = "new name";
}

public Widget Do(Widget widget) { // 3
    widget.Name = "new name";
    return widget;
}

我想和几个问题一起玩Devil's Advocate并收集回复,以帮助我解释为什么我被选项3所吸引。

选项1:为什么只修改传入的Widget?你只是“返回”一个对象。为什么不直接使用传入的对象?

选项2:为什么返回void?为什么不在签名中传达您将使用实际的内存指针到参数对象本身?

选项3:您返回的是您传入的同一个对象,这不奇怪吗?

4 个答案:

答案 0 :(得分:12)

选项1:这是最常用的方法 - 如果您不想修改参考本身,则不需要参考。确保正确命名方法,以期确保修改传递的对象。

选项2:这仅在您希望更改传递的引用本身时有用,即创建新的Widget实例或将引用设置为指向到一个现有的小部件(如果你想保持实例总数低,如果它们都具有相同的属性,这可能很有用,请参阅Flyweight pattern,通常返回的小部件在这种情况下应该是不可变的,你会使用一个工厂代替)。在你的情况下,这似乎不合适。

选项3:这允许流畅的“构建器”方法 - 也有其好处,即将Widget的更改链接到一些人认为更具表现力和自我记录的方式。另请参阅Fluent interface

答案 1 :(得分:6)

选项1:

精细。正是我用的东西。您可以改变窗口小部件的内容,但不能改变窗口小部件本身。

选项2:

没有。不可以。您不需要修改引用本身,因此您不需要使用ref。如果您修改了引用本身(例如widget = new Widget(),那么out / ref是正确的选择,但根据我的经验,很少需要。

选项3:
与选项1类似。但可以用流畅的样式API链接。我个人不喜欢这个。如果我返回副本并保持原始对象不变,我只会使用该签名。


但最重要的是你如何命名方法。该名称需要明确暗示原始对象是变异的。

在许多情况下,我会选择选项4:使类型不可变并返回副本。但是对于那些显然是实体而非价值的小部件,这没有任何意义。

答案 2 :(得分:4)

3个选项之间实际上没有任何功能差异。 (存在差异,没有一个与您的问题相关。)保持简单 - 使用选项1.

答案 3 :(得分:1)

我认为选项1和选项3都是可行的选择。选项3具有自我记录的优点,因为它意味着您正在修改方法中的Widget。我认为最糟糕的选择是选项2.我的ref关键字意味着您正在修改对象的引用,您肯定不会这样做。