我可以修改传递的方法参数吗

Can I modify a passed method parameter

提问人:Brad 提问时间:10/22/2010 最后编辑:one noaBrad 更新时间:11/15/2023 访问量:18443

问:

我的直觉告诉我不应该做以下事情。我没有收到任何关于它的警告。

void test(DateTime d)
{
 d = d.AddDays(2);
//do some thing with d
 }

还是这样更合适

 void test(DateTime d)
 {
 DateTime _d = d.AddDays(1);
//do some thing with _d
 }

出于某种原因,我总是像第二个示例一样处理传递的参数。 但我不确定这是否真的是 nessesry......也许这只是不合时宜的代码。

我不认为调用方法会使用修改后的值。 任何人都有任何意见

C# 参数传递

评论


答:

5赞 Aliostad 10/22/2010 #1

您可以更改它,但更改不会返回给调用方。

如果是 ValueType ->则发送对象的副本

如果是 RefernceType ->则对象引用的副本将按值发送。通过这种方式,可以更改对象的属性,但不能更改引用本身 - 调用方无论如何都不会看到更改。

如果发送了 -> 可以更改引用。ref

在 C++ 中,您可以使用来阻止更改,但 C# 没有。这只是为了防止程序员错误地尝试更改它 - 取决于在哪里使用。constconst

评论

0赞 Harper Shelby 10/22/2010
这取决于细节。在这个非常具体的示例中,由于 DateTime 是一个结构,并且具有值语义,因此这是真的。其他具有引用语义的参数会将该更改反映回调用方。
0赞 Jon Skeet 10/22/2010
@Harper:如果 OP 更改了参数的值,而不是对参数值所引用的对象进行更改,则不会。有关这两者之间差异的示例,请参阅我的回答。
0赞 Anthony Pegram 10/22/2010
@Harper,除非它是专门的(或)参数,否则不会反映在结构或类的调用站点上。对引用类型的成员执行的操作将反映,而对引用本身执行的操作则不会。foo = ...refout
0赞 Harper Shelby 10/22/2010
@Jon Skeet:好的,我省略了第三个选项。人们认为C++令人困惑!
0赞 Justin Niessner 10/22/2010 #2

如果希望能够访问原始值,请使用第二种方法。

如果你不关心原始值,你可以使用任何一个(不过我可能仍然会使用第二个)。

无论哪种方式,在这种情况下,您都不会损害其他人的值(即使您重新分配值,它也不会将其返回给调用者)。

25赞 Jon Skeet 10/22/2010 #3

参数值的更改对调用方不可见,除非它是 or 参数。refout

如果对参数引用的引用类型对象进行更改,则情况并非如此。例如:

public void Foo(StringBuilder b)
{
    // Changes the value of the parameter (b) - not seen by caller
    b = new StringBuilder();
}

public void Bar(StringBuilder b)
{
    // Changes the contents of the StringBuilder referred to by b's value -
    // this will be seen by the caller
    b.Append("Hello");
}

最后,如果参数通过引用传递,会看到更改:

public void Baz(ref StringBuilder b)
{
    // This change *will* be seen
    b = new StringBuilder();
}

有关更多信息,请参阅我关于参数传递的文章