C# 为什么在传递对象时使用“ref”关键字?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/186891/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why use the 'ref' keyword when passing an object?
提问by Ryan
If I am passing an object to a method, why should I use the ref keyword? Isn't this the default behaviour anyway?
如果我将对象传递给方法,为什么要使用 ref 关键字?无论如何,这不是默认行为吗?
For example:
例如:
class Program
{
static void Main(string[] args)
{
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(t);
Console.WriteLine(t.Something);
}
static public void DoSomething(TestRef t)
{
t.Something = "Bar";
}
}
public class TestRef
{
public string Something { get; set; }
}
The output is "Bar" which means that the object was passed as a reference.
输出是“Bar”,这意味着该对象作为引用传递。
采纳答案by Scott Langham
Pass a ref
if you want to change what the object is:
ref
如果要更改对象的内容,请传递 a :
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(ref t);
void DoSomething(ref TestRef t)
{
t = new TestRef();
t.Something = "Not just a changed t, but a completely different TestRef object";
}
After calling DoSomething, t
does not refer to the original new TestRef
, but refers to a completely different object.
调用 DoSomething 后,t
并不是指原来的new TestRef
,而是指一个完全不同的对象。
This may be useful too if you want to change the value of an immutable object, e.g. a string
. You cannot change the value of a string
once it has been created. But by using a ref
, you could create a function that changes the string for another one that has a different value.
如果您想更改不可变对象的值,例如 a ,这可能也很有用string
。a 的值string
一旦创建就无法更改。但是通过使用 a ref
,您可以创建一个函数来更改另一个具有不同值的字符串。
Edit: As other people have mentioned. It is not a good idea to use ref
unless it is needed. Using ref
gives the method freedom to change the argument for something else, callers of the method will need to be coded to ensure they handle this possibility.
编辑:正如其他人所提到的。ref
除非需要,否则使用不是一个好主意。Usingref
使方法可以自由地更改其他内容的参数,需要对方法的调用者进行编码以确保他们处理这种可能性。
Also, when the parameter type is an object, then object variables always act as references to the object. This means that when the ref
keyword is used you've got a reference to a reference. This allows you to do things as described in the example given above. But, when the parameter type is a primitive value (e.g. int
), then if this parameter is assigned to within the method, the value of the argument that was passed in will be changed after the method returns:
此外,当参数类型是对象时,对象变量始终充当对象的引用。这意味着当使用ref
关键字时,您将获得对引用的引用。这允许您按照上面给出的示例进行操作。但是,当参数类型是原始值(例如int
)时,如果在方法内部分配了该参数,则在方法返回后传入的参数的值将发生变化:
int x = 1;
Change(ref x);
Debug.Assert(x == 5);
WillNotChange(x);
Debug.Assert(x == 5); // Note: x doesn't become 10
void Change(ref int x)
{
x = 5;
}
void WillNotChange(int x)
{
x = 10;
}
回答by Andrew
If you're passing a value, however, things are different. You can force a value to be passed by reference. This allows you to pass an integer to a method, for example, and have the method modify the integer on your behalf.
但是,如果您要传递一个值,情况就不同了。您可以强制通过引用传递值。例如,这允许您将整数传递给方法,并让方法代表您修改整数。
回答by Rinat Abdullin
With ref
you can write:
随着ref
你可以写:
static public void DoSomething(ref TestRef t)
{
t = new TestRef();
}
And t will be changed after the method has completed.
并且 t 将在方法完成后更改。
回答by Ferruccio
Since TestRef is a class (which are reference objects), you can change the contents inside t without passing it as a ref. However, if you pass t as a ref, TestRef can change what the original t refers to. i.e. make it point to a different object.
由于 TestRef 是一个类(它们是引用对象),因此您可以更改 t 中的内容而无需将其作为 ref 传递。但是,如果您将 t 作为 ref 传递,则 TestRef 可以更改原始 t 所指的内容。即使它指向不同的对象。
回答by Isak Savo
By using the ref
keyword with reference types you are effectively passing a reference to the reference. In many ways it's the same as using the out
keyword but with the minor difference that there's no guarantee that the method will actually assign anything to the ref
'ed parameter.
通过将ref
关键字与引用类型一起使用,您可以有效地传递对引用的引用。在许多方面,它与使用out
关键字相同,但有一点不同,即不能保证该方法实际上将任何内容分配给ref
'ed 参数。
回答by pezi_pink_squirrel
This is like passing a pointer to a pointer in C. In .NET this will allow you to change what the original T refers to, personallythough I think if you are doing that in .NET you have probably got a design issue!
这就像在 C 中传递一个指向指针的指针。在 .NET 中,这将允许您更改原始 T 所指的内容,尽管我个人认为如果您在 .NET 中这样做,您可能会遇到设计问题!
回答by xtofl
Ref denotes whether the function can get its hands on the object itself, or only on its value.
Ref 表示函数是否可以获取对象本身,或者只能获取它的值。
Passing by reference is not bound to a language; it's a parameter binding strategy next to pass-by-value, pass by name, pass by need etc...
通过引用传递不受语言约束;它是按值传递、按名称传递、按需要传递等旁边的参数绑定策略...
A sidenote: the class name TestRef
is a hideously bad choice in this context ;).
旁注:TestRef
在这种情况下,类名是一个非常糟糕的选择;)。
回答by Jon Skeet
You need to distinguish between "passing a reference by value", and "passing a parameter/argument by reference".
您需要区分“按值传递引用”和“按引用传递参数/参数”。
I've written a reasonably long article on the subjectto avoid having to write carefully each time this comes up on newsgroups :)
回答by Ricardo Amores
In .NET when you pass any parameter to a method, a copy is created. In value types means that any modification you make to the value is at the method scope, and is lost when you exit the method.
在 .NET 中,当您将任何参数传递给方法时,会创建一个副本。在值类型中意味着您对值所做的任何修改都在方法范围内,并且在您退出方法时会丢失。
When passing a Reference Type, a copy is also made, but it is a copy of a reference, i.e. now you have TWO references in memory to the same object. So, if you use the reference to modify the object, it gets modified. But if you modify the reference itself - we must remember it is a copy - then any changes are also lost upon exiting the method.
传递引用类型时,也会生成一个副本,但它是引用的副本,即现在您在内存中有两个对同一对象的引用。所以,如果你使用引用来修改对象,它就会被修改。但是如果你修改引用本身——我们必须记住它是一个副本——那么在退出方法时任何更改也会丢失。
As people have said before, an assignment is a modification of the reference, thus is lost:
正如人们之前所说,赋值是对引用的修改,因此丢失了:
public void Method1(object obj) {
obj = new Object();
}
public void Method2(object obj) {
obj = _privateObject;
}
The methods above does not modifies the original object.
上述方法不会修改原始对象。
A little modification of your example
对您的示例稍作修改
using System;
class Program
{
static void Main(string[] args)
{
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(t);
Console.WriteLine(t.Something);
}
static public void DoSomething(TestRef t)
{
t = new TestRef();
t.Something = "Bar";
}
}
public class TestRef
{
private string s;
public string Something
{
get {return s;}
set { s = value; }
}
}
回答by guneysus
ref
mimics (or behaves) as a global area just for two scopes:
ref
模仿(或表现)为仅适用于两个范围的全局区域:
- Caller
- Callee.
- 呼叫者
- 被叫。