修改方法或返回结果中的方法参数

时间:2009-02-17 03:48:10

标签: c# .net

之间有什么区别
private void DoSomething(int value) {
    value++;
}

private int DoSomething(int value) {
   return value++;
}

用作

DoSomething(value);

value = DoSomething(value);

7 个答案:

答案 0 :(得分:44)

您所说的是通过引用传递传递值之间的区别,这在概念上类似于值类型与引用类型的概念

如果您将值类型传递给方法,则必须使用第二个示例;否则你只是递增一个存在于DoSomething()范围内的整数。试一试:如果执行第一个例子,在运行DoSomething()之后,int的值将保持不变。

但是,如果您传递的不是值类型(例如对象foo),则实际上将引用传递给原始对象。你在DoSomething()中做的任何事情都会在方法之外生效,因为你仍然指的是同一个对象。

您可以通过编写以下内容来完成您在第一个示例中尝试的内容:

void DoSomething(ref int value)

指示.NET传递对项的引用,而不管它是否为值类型。

在MSDN上的 Value Types vs Reference Types 上查看此文章,了解更详细的信息。

此外,作为zodoz points out(适当地提升),通过返回value++,您将返回然后递增。要返回递增的值,请使用++value

答案 1 :(得分:28)

返回一个值。

为什么?

正确性,可读性和自我文档

有意且易于理解的代码优于副作用代码。考虑:

float area = pi * Square(r);

VS

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; }

这显然是正确的。 VS

void DoSomething(int value)
   { value++; }

这似乎是正确的,并且编译得很好,但实际上只是一个无操作。你真正想要的是:

void DoSomething(ref int value)
   { value++; }

// client code:
DoSomething(ref a);

变量便宜

许多命名良好的变量优于少数重用的通用变量。抵制过早优化的诱惑,您需要减少局部变量的数量以提高系统性能的可能性非常小。 再次,变量便宜,不要重复使用变量!

<强>可测

考虑:

Assert.IsTrue(Square(2) == 4);

VS

float a = 2;
Square(a);
Assert.IsTrue(a == 4);

避免突变优先于返回值还有许多其他优点。数学将函数定义为输入值与输出值的映射不仅仅是偶然的。

答案 2 :(得分:6)

其他人似乎都在暗示变量传递的差异,但我发现了一些不同的东西:

如果您显示的示例代码是您正在查看的内容的简化,那么您可能需要在第二个示例中注意:

private int DoSomething(int value) {
    return value++;
}

value将返回然后增量。因此,如果您执行以下操作:

public Main() {
    int val = 1;
    Console.writeln(DoSomething(val));
}

您的输出将为1

让我知道这是否有帮助。

答案 3 :(得分:5)

只是第一个不起作用,因为你正在使用价值副本。

您可以执行类似

的操作
private int DoSomething(ref int value)
{
  value++;
}

并将其称为

DoSomething(ref value);

这会更改要通过引用传递的值。但实际上,唯一的理由就是如果你想从函数中返回多个东西。通常有更好的方法。

对于额外的奖励知识,还有out关键字与ref类似,但不需要首先初始化值。

答案 4 :(得分:2)

在第一个示例中,int参数value递增,但在方法结束时被销毁,除非使用ref或{{3},否则无法获取方法外的值关键字。

例如:

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修改,无论它是值类型还是引用类型,当通过引用传递时,没有值类型的装箱。

答案 5 :(得分:0)

对于大多数编程语言,您需要通过参数传递参数来更改void函数。函数通常不能改变其参数的值;相反,它会创建参数的副本并使用它。

为了使用实际变量,您必须更改函数标题以接受对变量的引用,并使用前面的&符号(&amp;),如下所示:

private void DoSomething(int &value)

希望有所帮助!

答案 6 :(得分:0)

由于您使用的是postfix ++,因此返回的值是该数字的原始值。此外,由于您传递的是数字的副本而不是数字本身(即通过引用),因此对值所做的更改不会影响您传递的变量。

所以这样的程序:

int value=1;
std::cout<<value<<std::endl;
value = DoSomething(value);
std::cout<<value<<std::endl;

DoSomething(value);
std::cout<<value<<std::endl;

输出如下:

1
1
1

如果您在返回时使用前缀++,或者如果您要在非返回函数中通过引用传递,则相同的程序将输出如下。

1
2
3

希望这会有所帮助。