您是否更愿意返回修改后的对象?

时间:2009-06-03 05:01:10

标签: c# class

Class c = new Class( { Prop = "Initial" } );

我上面有上课。你会如何创建一个修改它的方法?

public Class ModifyIt(Class c)
{
    c.Prop = "changed";
    return c;
}

public void ModifyIt(Class c)
{
    c.Prop = "changed";
}

然后这样叫......

Class c = ModifyIt(c);
Console.WriteLine(c.Prop);
// changed

或者

ModifyIt(c)
Console.WriteLine(c.Prop);
// changed

您的偏好是什么?

6 个答案:

答案 0 :(得分:6)

就个人而言,我更喜欢command-query separation - 即,返回结果的方法不应该是mutator,反之亦然。我理解return this人群的论点,即“链接”电话的简易性:

foo.ChangeThis(23).ChangeThat(45).AndAlso(67);

但将这些案例编码为

绝对不是太糟糕
var x=foo;
x.ChangeThis(23); x.ChangeThat(45); x.AndAlso(67);

同时,“命令查询分离”的优势(在绝大多数情况下,虽然不可否认只是100%),正如wikipeida网址所讨论的那样,忍受...

答案 1 :(得分:3)

返回对象实例的选择取决于具体情况。

builder pattern中可以看到通过该方法返回对象的常见情况,例如StringBuilder类:

new StringBuilder("Hello").Append(" ").Append("World!").ToString();

但总的来说,如果不执行此类method chaining,我会选择不返回任何内容。如果常见的用例是不使用返回的对象(并且只是丢弃它),这似乎是浪费。

答案 2 :(得分:2)

在第一种方式中执行它的很酷的事情是,它实际上在更改后返回项目,它允许方法链接。意思是你可以做这样的事情:

c.ModifyIt("hello").MessWithIt("World").ReallyScrewWithIt("!!!");

如果你可以预见到需要链接的特定类是有意义的,那么返回实例。如果没有,那么你可以让它无效。一个很好的例子是StringBuilder类,它允许你做类似的事情:

myStringBuilder.Replace("!", "?").Append("Something").Remove(4,3);

答案 3 :(得分:1)

我个人更喜欢构建像ModifyIt这样的函数,并将其放在我正在创建的类中,如果可能的话。我说的原因是在我正在修改调用变量的两种方法中,因为我通过引用传递它。当然,我不能为所有函数执行此操作,但将ref放入函数调用有助于澄清我通过引用传递变量,而不是通过值传递变量。例如:

public Class ModifyIt(ref Class c)

为什么呢?因为当我回来读取我通过引用传递值的代码时,我很容易忘记,然后更可能对代码执行“坏”操作。

答案 4 :(得分:0)

首先,如果你只是改变一个属性,我根本就没有单独的修改功能;我只是直接改变房产。有了这个,我们假设你给出了一个更复杂的事情的简单例子,在修改函数中可能有几个不同的变化。

我会使用返回'Class'对象的那个。它允许您将多个呼叫链接在一起。同样,我假设这是一个实际上更复杂的系统的简单示例;假设你有MakeModification(),MakeAnotherModification()和MakeAThirdModification()。如果您返回“Class”对象,则可以获得以下语法:

Class c = new Class();
c.MakeModification().MakeAnotherModification().MakeAThirdModification();

答案 5 :(得分:0)

实际上我更喜欢第二种风格,因为该方法是一个mutator,因此,预计不会返回一个新值,而是希望修改实际值。但是,您可能需要指示ModifyIt接受ref变量,以指示将修改实际c。这里的c是按值传递的,虽然它是一个引用类型,但是按值传递引用类型和通过引用传递引用类型之间仍然存在差异。请参阅以下内容:

public void ModifyIt(Myclass c) { c = new MyClass(); } 

在上面的例子中,c变量将通过值传递(即来自引用的副本将被传递并修改为指向新的instanitiated对象,这反过来意味着你将拥有两个MyClass类型的对象case。这是一个例子来说明:

Myclass s = new MyClass () { prop = "value" }; ModifyIt(s); Console.WriteLine(s.prob); // this will print "value"

尽管MOdifyIT对新对象进行了实例化,这应该意味着prob将被初始化为null,但它实际上没有实例化s,它实例化了s的副本。不同于如果s被ref传递的情况。
希望这可以帮助!