修改方法或返回结果中的方法参数
有什么区别
private void DoSomething(int value) { value++; }
和
private int DoSomething(int value) { return value++; }
当用作任何一种
DoSomething(value);
与
value = DoSomething(value);
您正在讨论通过引用 传递和传递值之间的区别,这在概念上类似于值类型与引用类型的概念 。
如果将值类型传递给方法,则必须使用第二个示例; 否则你只是递增一个存在于DoSomething()范围内的整数。 试一试:如果执行第一个例子,在运行DoSomething()之后,int的值将保持不变。
但是,如果要传递的值不是值类型(比如对象foo),则实际上是在传递对原始对象的引用 。 你在DoSomething()中做的任何事情也会在方法之外生效,因为你仍然指的是同一个对象。
您可以通过编写以下内容来完成您在第一个示例中尝试的内容:
void DoSomething(ref int value)
这指示.NET传递对项的引用,而不管它是否为值类型。
有关详细信息,请参阅MSDN上的值类型与引用类型的此文章。
此外,正如zodoz指出的那样 (适当地提升 ),通过返回value++
你将返回然后递增。 要返回递增的值,请使用++value
。
返回一个值。
为什么?
正确性,可读性和自我文档
有意且易于理解的代码优于副作用代码。 考虑:
float area = pi * Square(r);
与
Square(r); float area = pi * r; // ... intervening code float x = r * 5; // did you mean to use the original r or r-squared here?
在第一个例子中还要考虑通过可组合性的简洁性的优点。
考虑方法本身,比较:
int DoSomething(int value) { return value+1; }
这显然是正确的。 与
void DoSomething(int value) { value++; }
这似乎是正确的,并将编译得很好,但实际上只是一个无操作。 你真正想要的是这个:
void DoSomething(ref int value) { value++; } // client code: DoSomething(ref a);
变量很便宜
许多命名良好的变量优于少数重用的通用变量。 抵制过早优化的诱惑,您需要减少局部变量的数量以提高系统性能的可能性非常小。 再次,变量是便宜的,不要重复变量!
可测性
考虑:
Assert.IsTrue(Square(2) == 4);
与
float a = 2; Square(a); Assert.IsTrue(a == 4);
避免突变优先于返回值还有许多其他优点。 数学将函数定义为输入值到输出值的映射不仅仅是一个意外。
只是第一个不起作用,因为你在一个价值副本上运作。
你可以做点什么
private int DoSomething(ref int value) { value++; }
并称之为
DoSomething(ref value);
这会更改要通过引用传递的值。 但实际上,唯一的理由就是如果你想从函数中返回多个东西。 通常有更好的方法。
对于额外的奖励知识,还有out关键字与ref类似,但不需要首先初始化值。
其他人似乎都在暗示变量传递的差异,但我注意到了一些不同的东西:
如果您显示的示例代码是您正在查看的内容的简化,那么您可能需要在第二个示例中注意:
private int DoSomething(int value) { return value++; }
该value
将返回然后递增。 因此,如果您执行以下操作:
public Main() { int val = 1; Console.writeln(DoSomething(val)); }
你的输出将是1
。
如果这有帮助,请告诉我。
在第一个示例中,int参数value
递增,但在方法结束时销毁,除非使用ref或out关键字,否则无法获取方法外的值。
例如:
private int DoSomething(ref int value) { return value++; } // ... int myValue = 5; DoSomething(ref myValue); // Now myValue is 6.
Ref和out参数传递模式用于允许方法更改方法调用者传入的变量。 ref和out之间的主要区别可能很微妙但很重要。
每个参数传递模式都旨在满足不同的编程需求。
取出参数的方法的调用者不需要分配给在调用之前作为out参数传递的变量; 但是,该方法需要在返回之前分配给out参数。
考虑参数的一种方法是它们就像方法的附加返回值。 当方法应返回多个值时,它们很方便。
ref参数导致参数通过引用传递。 结果是,当控制传递回调用方法时,方法中参数的任何更改都将反映在该变量中。
不要将引用传递的概念与引用类型的概念混淆 。
这两个概念没有关系; 方法参数可以通过ref修改,无论它是值类型还是引用类型,当通过引用传递时,没有值类型的装箱。
对于大多数编程语言,您需要通过引用传递参数来更改void函数。 函数通常不能改变其参数的值; 相反,它会创建参数的副本并改为使用它。
为了使用实际变量,您必须更改函数头以接受对变量的引用,并使用前面的&符号(&):
private void DoSomething(int &value)
希望有所帮助!
由于您使用的是postfix ++,因此返回的值是该数字的原始值。 此外,由于您传递的是数字的副本而不是数字本身(即通过引用),因此对值所做的更改不会影响您传递的变量。
所以像这样的程序:
int value=1; std::cout<
应输出如下:
1 1 1
如果您在返回时使用前缀++,或者如果您要在非返回函数中通过引用传递,则相同的程序将输出如下。
1 2 3
希望这会有所帮助。