提问人:JMS 提问时间:2/17/2009 最后编辑:one noaJMS 更新时间:11/15/2023 访问量:70786
在方法中修改方法参数或返回结果
Modify method parameter within method or return result
问:
两者之间有什么区别
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
评论
对于大多数编程语言,您需要通过引用传递参数来更改 void 函数。函数通常不能更改其参数的值;相反,它会创建参数的副本并改用该副本。
为了使用实际变量,您必须更改函数标头以接受对变量的引用,前面的 &) 号如下所示:
private void DoSomething(int &value)
希望对您有所帮助!
评论
private unsafe void DoSomething(int* value)
在第一个示例中,int 参数递增,但在方法结束时被销毁,除非使用 ref 或 out 关键字,否则无法获取方法外部的值。value
例如:
private int DoSomething(ref int value) {
return value++;
}
// ...
int myValue = 5;
DoSomething(ref myValue);
// Now myValue is 6.
Ref 和 out 参数传递模式用于允许方法更改方法调用方传入的变量。ref 和 out 之间的主要区别可能很微妙,但很重要。
每种参数传递模式都旨在满足不同的编程需求。
在调用之前,采用 out 参数的方法的调用方不需要分配给作为 out 参数传递的变量;但是,在返回之前,需要将该方法分配给 out 参数。
考虑参数的一种方法是,它们类似于方法的附加返回值。当方法应返回多个值时,它们很方便。
ref 参数导致通过引用传递参数。其效果是,当控制权传递回调用方法时,对方法中参数的任何更改都将反映在该变量中。
不要将引用传递的概念与引用类型的概念混淆。
这两个概念不相关;一个方法参数可以被 ref 修改,不管它是值类型还是引用类型,一个值类型在通过引用传递时没有装箱。
简单地说,第一个是行不通的,因为你正在对价值的副本进行操作。
你可以做这样的事情
private int DoSomething(ref int value)
{
value++;
}
并称它为
DoSomething(ref value);
这将更改要通过引用传入的值。但实际上,这样做的唯一原因是,如果你想从函数中返回多个东西。通常有更好的方法。
对于额外的奖励知识,还有一个类似于 ref 的 out 关键字,但不需要先初始化值。
其他人似乎都在暗示变量传递的差异,但我注意到了一些不同的东西:
如果您显示的示例代码是您正在查看的内容的简化,那么您可能需要在第二个示例中注意:
private int DoSomething(int value) {
return value++;
}
将返回然后递增。因此,如果您执行以下操作:value
public Main() {
int val = 1;
Console.writeln(DoSomething(val));
}
您的输出将是 。1
让我知道这是否有帮助。
返回一个值。
为什么?
正确性、可读性和自文档
有意且易于理解的代码比副作用代码更好。考虑:
float area = pi * Square(r);
HSP的
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; }
这显然是正确的。HSP的
void DoSomething(int value)
{ value++; }
这似乎是正确的,并且编译得很好,但实际上只是一个不操作。你真正想要的是这个:
void DoSomething(ref int value)
{ value++; }
// client code:
DoSomething(ref a);
变量很便宜
许多命名良好的变量比少数重用的通用变量更可取。抵制过早优化的诱惑,您需要减少局部变量的数量以提高系统性能的机会微乎其微。同样,变量很便宜,不要重用变量!
测试
考虑:
Assert.IsTrue(Square(2) == 4);
HSP的
float a = 2;
Square(a);
Assert.IsTrue(a == 4);
与返回值相比,避免突变还有许多其他优点。数学将函数定义为输入值到输出值的映射,这不仅仅是偶然的。
评论
下一个:在方法中修改方法参数或返回结果
评论