C# “ref”和“out”关键字有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/388464/
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
What's the difference between the 'ref' and 'out' keywords?
提问by TK.
I'm creating a function where I need to pass an object so that it can be modified by the function. What is the difference between:
我正在创建一个函数,我需要在其中传递一个对象,以便该函数可以修改它。有什么区别:
public void myFunction(ref MyClass someClass)
and
和
public void myFunction(out MyClass someClass)
Which should I use and why?
我应该使用哪个,为什么?
采纳答案by Rune Grimstad
ref
tells the compiler that the object is initialized before entering the function, while out
tells the compiler that the object will be initialized inside the function.
ref
告诉编译器对象在进入函数之前被初始化,同时out
告诉编译器对象将在函数内部初始化。
So while ref
is two-ways, out
is out-only.
所以whileref
是双向的,out
是out-only的。
回答by Ruben Bartelink
You should use out
in preference wherever it suffices for your requirements.
out
只要满足您的要求,您就应该优先使用它。
回答by Albic
Since you're passing in a reference type (a class) there is no need use ref
because per default only a referenceto the actual object is passed and therefore you always change the object behind the reference.
由于您传递的是引用类型(一个类),因此没有必要使用,ref
因为默认情况下只传递对实际对象的引用,因此您总是更改引用后面的对象。
Example:
例子:
public void Foo()
{
MyClass myObject = new MyClass();
myObject.Name = "Dog";
Bar(myObject);
Console.WriteLine(myObject.Name); // Writes "Cat".
}
public void Bar(MyClass someObject)
{
someObject.Name = "Cat";
}
As long you pass in a class you don't have to use ref
if you want to change the object inside your method.
只要您传入一个类,ref
如果您想更改方法中的对象,就不必使用它。
回答by Anton Kolesov
The ref
modifier means that:
该ref
修改意味着:
- The value is already set and
- The method can read and modify it.
- 该值已经设置并且
- 该方法可以读取和修改它。
The out
modifier means that:
该out
修改意味着:
- The Value isn't set and can't be read by the method untilit is set.
- The method mustset it before returning.
- 值未设置且在设置之前无法被方法读取。
- 该方法必须在返回之前设置它。
回答by mmmmmmmm
"Baker"
“面包师”
That's because the first one changes your string-reference to point to "Baker". Changing the reference is possible because you passed it via the ref keyword (=> a reference to a reference to a string). The Second call gets a copy of the reference to the string.
那是因为第一个将您的字符串引用更改为指向“贝克”。更改引用是可能的,因为您通过 ref 关键字(=> 对字符串引用的引用)传递了它。第二个调用获取字符串引用的副本。
string looks some kind of special at first. But string is just a reference class and if you define
字符串起初看起来有些特别。但字符串只是一个参考类,如果你定义
string s = "Able";
then s is a reference to a string class that contains the text "Able"! Another assignment to the same variable via
那么 s 是对包含文本“Able”的字符串类的引用!通过对同一变量的另一个赋值
s = "Baker";
does not change the original string but just creates a new instance and let s point to that instance!
不会更改原始字符串,而只是创建一个新实例并让 s 指向该实例!
You can try it with the following little code example:
您可以使用以下小代码示例进行尝试:
string s = "Able";
string s2 = s;
s = "Baker";
Console.WriteLine(s2);
What do you expect? What you will get is still "Able" because you just set the reference in s to another instance while s2 points to the original instance.
你能指望什么?您将得到的仍然是“Able”,因为您只是将 s 中的引用设置为另一个实例,而 s2 指向原始实例。
EDIT: string is also immutable which means there is simply no method or property that modifies an existing string instance (you can try to find one in the docs but you won't fins any :-) ). All string manipulation methods return a new string instance! (That's why you often get a better performance when using the StringBuilder class)
编辑:字符串也是不可变的,这意味着根本没有修改现有字符串实例的方法或属性(您可以尝试在文档中找到一个,但您不会找到任何 :-) )。所有字符串操作方法都返回一个新的字符串实例!(这就是为什么您在使用 StringBuilder 类时通常会获得更好的性能)
回答by Michael Blackburn
Let's say Dom shows up at Peter's cubicle about the memo about the TPS reports.
假设 Dom 出现在 Peter 的小隔间,关于 TPS 报告的备忘录。
If Dom were a ref argument, he would have a printed copy of the memo.
如果 Dom 是一个 ref 参数,他会有一份备忘录的打印副本。
If Dom were an out argument, he'd make Peter print a new copy of the memo for him to take with him.
如果 Dom 是个外人,他会让 Peter 打印一份备忘录的新副本,让他随身携带。
回答by Mangesh Pimpalkar
Mind well that the reference parameter which is passed inside the function is directly worked on.
请注意,直接处理函数内部传递的引用参数。
For example,
例如,
public class MyClass
{
public string Name { get; set; }
}
public void Foo()
{
MyClass myObject = new MyClass();
myObject.Name = "Dog";
Bar(myObject);
Console.WriteLine(myObject.Name); // Writes "Dog".
}
public void Bar(MyClass someObject)
{
MyClass myTempObject = new MyClass();
myTempObject.Name = "Cat";
someObject = myTempObject;
}
This will write Dog, not Cat. Hence you should directly work on someObject.
这将写入 Dog,而不是 Cat。因此你应该直接在 someObject 上工作。
回答by BBB
Extending the Dog, Cat example. The second method with ref changes the object referenced by the caller. Hence "Cat" !!!
扩展狗,猫的例子。带有 ref 的第二种方法更改调用者引用的对象。因此“猫”!!!
public static void Foo()
{
MyClass myObject = new MyClass();
myObject.Name = "Dog";
Bar(myObject);
Console.WriteLine(myObject.Name); // Writes "Dog".
Bar(ref myObject);
Console.WriteLine(myObject.Name); // Writes "Cat".
}
public static void Bar(MyClass someObject)
{
MyClass myTempObject = new MyClass();
myTempObject.Name = "Cat";
someObject = myTempObject;
}
public static void Bar(ref MyClass someObject)
{
MyClass myTempObject = new MyClass();
myTempObject.Name = "Cat";
someObject = myTempObject;
}
回答by James Roland
I am going to try my hand at an explanation:
我将尝试解释一下:
I think we understand how the value types work right? Value types are (int, long, struct etc.). When you send them in to a function without a ref command it COPIES the data. Anything you do to that data in the function only affects the copy, not the original. The ref command sends the ACTUAL data and any changes will affect the data outside the function.
我想我们理解值类型是如何工作的吗?值类型是(int、long、struct 等)。当您将它们发送到没有 ref 命令的函数时,它会复制数据。您对函数中的数据所做的任何操作只会影响副本,而不是原始数据。ref 命令发送 ACTUAL 数据,任何更改都会影响函数外的数据。
Ok on to the confusing part, reference types:
好的,令人困惑的部分,引用类型:
Lets create a reference type:
让我们创建一个引用类型:
List<string> someobject = new List<string>()
When you new up someobject, two parts are created:
当您新建someobject 时,会创建两个部分:
- The block of memory that holds data for someobject.
- A reference (pointer) to that block of data.
- 保存someobject数据的内存块。
- 对该数据块的引用(指针)。
Now when you send in someobjectinto a method without ref it COPIES the referencepointer, NOT the data. So you now have this:
现在,当你在发送someobject成方法,无需裁判它复制的参考指针,而不是数据。所以你现在有这个:
(outside method) reference1 => someobject
(inside method) reference2 => someobject
Two references pointing to the same object. If you modify a property on someobjectusing reference2 it will affect the same data pointed to by reference1.
两个引用指向同一个对象。如果修改属性someobject使用给定2它会影响通过参考量指向相同的数据。
(inside method) reference2.Add("SomeString");
(outside method) reference1[0] == "SomeString" //this is true
If you null out reference2 or point it to new data it will not affect reference1 nor the data reference1 points to.
如果您将 reference2 清空或将其指向新数据,则不会影响 reference1 或 reference1 指向的数据。
(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true
The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject
Now what happens when you send someobjectby ref to a method? The actual referenceto someobjectgets sent to the method. So you now have only one reference to the data:
现在,当你发送的情况someobject通过裁判的方法?对某个对象的实际引用被发送到该方法。所以你现在只有一个对数据的引用:
(outside method) reference1 => someobject;
(inside method) reference1 => someobject;
But what does this mean? It acts exactly the same as sending someobject not by ref except for two main thing:
但是,这是什么意思?除了两个主要的事情之外,它的作用与不通过 ref 发送某个对象完全相同:
1) When you null out the reference inside the method it will null the one outside the method.
1)当您将方法内的引用设为 null 时,它会将方法外的引用设为 null。
(inside method) reference1 = null;
(outside method) reference1 == null; //true
2) You can now point the reference to a completely different data location and the reference outside the function will now point to the new data location.
2) 您现在可以将引用指向一个完全不同的数据位置,函数外部的引用现在将指向新的数据位置。
(inside method) reference1 = new List<string>();
(outside method) reference1.Count == 0; //this is true
回答by Edwin
I may not be so good at this, but surely strings (even though they are technically reference types and live on the heap) are passed by value, not reference?
我可能不太擅长这个,但是字符串(即使它们在技术上是引用类型并且存在于堆中)肯定是按值传递的,而不是引用?
string a = "Hello";
string b = "goodbye";
b = a; //attempt to make b point to a, won't work.
a = "testing";
Console.WriteLine(b); //this will produce "hello", NOT "testing"!!!!
This why you need ref if you want changes to exist outside of the scope of the function making them, you aren't passing a reference otherwise.
这就是为什么如果您希望更改存在于创建它们的函数范围之外,则需要 ref 的原因,否则您不会传递引用。
As far as I am aware you only need ref for structs/value types and string itself, as string is a reference type that pretends it is but is not a value type.
据我所知,您只需要结构/值类型和字符串本身的 ref ,因为字符串是一种引用类型,它假装它是但不是值类型。
I could be completely wrong here though, I am new.
不过,我在这里可能完全错了,我是新手。