“ref”和“ref”有什么区别? 和“出”; 关键词?
我正在创建一个函数,我需要在其中传递一个对象,以便该函数可以修改它。 ?
public void myFunction(ref MyClass someClass)
和
public void myFunction(out MyClass someClass)
我应该使用哪个以及为什么
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(28)
ref
告诉编译器该对象在进入函数之前被初始化,而out
告诉编译器该对象将在函数内部初始化。因此,虽然
ref
是双向的,但out
是仅输出的。ref
tells the compiler that the object is initialized before entering the function, whileout
tells the compiler that the object will be initialized inside the function.So while
ref
is two-ways,out
is out-only.ref
修饰符意味着:out
修饰符意味着:The
ref
modifier means that:The
out
modifier means that:假设 Dom 出现在 Peter 的小隔间,查看有关 TPS 报告的备忘录。
如果 Dom 是一个参考论点,他就会有一份备忘录的打印副本。
如果多姆不同意,他会让彼得打印一份新的备忘录供他随身携带。
Let's say Dom shows up at Peter's cubicle about the memo about the TPS reports.
If Dom were a ref argument, he would have a printed copy of the memo.
If Dom were an out argument, he'd make Peter print a new copy of the memo for him to take with him.
我将尝试解释一下:
我认为我们理解值类型如何工作? 值类型有(int、long、struct 等)。 当您将它们发送到没有 ref 命令的函数时,它会复制数据。 您在函数中对该数据所做的任何操作都只会影响副本,而不影响原始数据。 ref 命令发送实际数据,任何更改都会影响函数外部的数据。
好的,回到令人困惑的部分,引用类型:
让我们创建一个引用类型:
当您新建 someobject 时,会创建两个部分:
数据的。
现在,当您将某个对象发送到没有引用的方法中时,它会复制引用指针,而不是数据。 现在你有了这样的结果:
两个引用指向同一个对象。 如果您使用reference2修改某个对象的属性,它将影响reference1指向的相同数据。
如果您清空引用 2 或将其指向新数据,则不会影响引用 1 或引用 1 指向的数据。
现在,当您通过 ref 向方法发送 someobject 时会发生什么?
对某个对象的实际引用被发送到该方法。 因此,您现在只有一个对数据的引用:
但这意味着什么? 它的行为与不通过 ref 发送某个对象完全相同,除了以下两点之外:
1)当您清空方法内部的引用时,它将清空方法外部的引用。
2) 您现在可以将引用指向完全不同的数据位置,并且函数外部的引用现在将指向新的数据位置。
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.
Ok on to the confusing part, reference types:
Lets create a reference type:
When you new up someobject, two parts are created:
of data.
Now when you send in someobject into a method without ref it COPIES the reference pointer, NOT the data. So you now have this:
Two references pointing to the same object. If you modify a property on someobject using reference2 it will affect the same data pointed to by reference1.
If you null out reference2 or point it to new data it will not affect reference1 nor the data reference1 points to.
Now what happens when you send someobject by ref to a method?
The actual reference to someobject gets sent to the method. So you now have only one reference to the data:
But what does this mean? It acts exactly the same as sending someobject not by ref except for two main thing:
1) When you null out the reference inside the method it will null the one outside the method.
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.
引用和出 。
只要能够满足您的要求,您就应该优先使用
out
。ref is in and out.
You should use
out
in preference wherever it suffices for your requirements.out:
在 C# 中,一种方法只能返回一个值。 如果您想返回多个值,可以使用 out 关键字。 out 修饰符以引用返回的形式返回。 最简单的答案是使用关键字“out”从方法中获取值。
ref:
在 C# 中,当您将 int、float、double 等值类型作为实参传递给方法参数时,它是按值传递的。 因此,如果修改参数值,不会影响方法调用中的参数。 但如果你用“ref”关键字标记参数,它将反映在实际变量中。
out:
In C#, a method can return only one value. If you like to return more than one value, you can use the out keyword. The out modifier return as return-by-reference. The simplest answer is that the keyword “out” is used to get the value from the method.
ref:
In C#, when you pass a value type such as int, float, double etc. as an argument to the method parameter, it is passed by value. Therefore, if you modify the parameter value, it does not affect argument in the method call. But if you mark the parameter with “ref” keyword, it will reflect in the actual variable.
ref 表示 ref 参数中的值已经设置,该方法可以读取和修改它。
使用ref关键字就等于说调用者负责初始化参数的值。
out告诉编译器对象的初始化是由
函数,函数必须分配给 out 参数。
不允许将其保留为未分配状态。
https://www.codemaggot.com/ref-and-out-keywords/
ref means that the value in the ref parameter is already set, the method can read and modify it.
Using the ref keyword is the same as saying that the caller is responsible for initializing the value of the parameter.
out tells the compiler that the initialization of object is the responsibility of
the function, the function has to assign to the out parameter.
It's not allowed to leave it unassigned.
https://www.codemaggot.com/ref-and-out-keywords/
扩展 Dog、Cat 的例子。 第二个带有 ref 的方法更改调用者引用的对象。 因此“猫”!
Extending the Dog, Cat example. The second method with ref changes the object referenced by the caller. Hence "Cat" !!!
ref
和out
的行为类似,但存在以下差异。ref
变量在使用前必须初始化。out
变量可以在不赋值的情况下使用out
参数必须被使用它的函数视为未赋值的值。 因此,我们可以在调用代码中使用已初始化的out
参数,但该值在函数执行时会丢失。ref
andout
behave similarly except following differences.ref
variable must be initialized before use.out
variable can be used without assignmentout
parameter must be treated as an unassigned value by the function that uses it. So, we can use initializedout
parameter in the calling code, but the value will be lost when the function executes.由于您传递的是引用类型(类),因此无需使用
ref
因为默认情况下仅传递对实际对象的引用,因此您总是会更改引用后面的对象。示例:
只要传入一个类,如果您想更改方法内的对象,就不必使用
ref
。Since you're passing in a reference type (a class) there is no need use
ref
because per default only a reference to the actual object is passed and therefore you always change the object behind the reference.Example:
As long you pass in a class you don't have to use
ref
if you want to change the object inside your method.对于那些通过例子学习的人(比如我),这是Anthony Kolesov 所说的。
我创建了一些 ref、out 和其他的最小示例来说明这一点。 我不讨论最佳实践,只是举例来理解差异。
https://gist.github.com/2upmedia/6d98a57b68d849ee7091
For those that learn by example (like me) here's what Anthony Kolesov is saying.
I've created some minimal examples of ref, out, and others to illustrate the point. I'm not covering best practices, just examples to understand the differences.
https://gist.github.com/2upmedia/6d98a57b68d849ee7091
对于那些寻求简洁答案的人。
For those looking concise answer.
“Baker”
这是因为第一个将您的字符串引用更改为指向“Baker”。 更改引用是可能的,因为您通过 ref 关键字传递了它(=> 对字符串引用的引用)。
第二个调用获取字符串引用的副本。
字符串一开始看起来有些特别。 但 string 只是一个引用类,如果您定义了 s ,
那么 s 就是对包含文本“Able”的字符串类的引用!
对同一变量的另一个赋值 via
不会更改原始字符串,而只是创建一个新实例并让 s 指向该实例!
您可以使用以下小代码示例进行尝试:
您期望什么?
您将得到的仍然是“Able”,因为您只是将 s 中的引用设置为另一个实例,而 s2 指向原始实例。
编辑:
string 也是不可变的,这意味着根本没有任何方法或属性可以修改现有的字符串实例(您可以尝试在文档中找到一个,但您不会找到任何:-))。 所有字符串操作方法都会返回一个新的字符串实例! (这就是为什么使用 StringBuilder 类时通常会获得更好的性能)
"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.
string looks some kind of special at first. But string is just a reference class and if you define
then s is a reference to a string class that contains the text "Able"!
Another assignment to the same variable via
does not change the original string but just creates a new instance and let s point to that instance!
You can try it with the following little code example:
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.
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)
输出:
return 语句可用于从函数中仅返回一个值。 但是,使用输出参数,您可以从函数返回两个值。 输出参数与引用参数类似,只不过它们将数据从方法中传输出来而不是传入方法中。
以下示例说明了这一点:
参考:
引用参数是对变量内存位置的引用。 当您通过引用传递参数时,与值参数不同,不会为这些参数创建新的存储位置。 引用参数表示与提供给方法的实际参数相同的内存位置。
在 C# 中,可以使用 ref 关键字声明引用参数。 以下示例演示了这一点:
Out:
A return statement can be used for returning only one value from a function. However, using output parameters, you can return two values from a function. Output parameters are like reference parameters, except that they transfer data out of the method rather than into it.
The following example illustrates this:
ref:
A reference parameter is a reference to a memory location of a variable. When you pass parameters by reference, unlike value parameters, a new storage location is not created for these parameters. The reference parameters represent the same memory location as the actual parameters that are supplied to the method.
In C#, you declare the reference parameters using the ref keyword. The following example demonstrates this:
除了允许您将其他人的变量重新分配给类的不同实例、返回多个值等之外,使用
ref
或out
还可以让其他人知道您的内容需要他们以及您打算如何处理他们提供的变量您不需要
ref
或out
如果您要做的只是修改在参数someClass
中传递的MyClass
实例内部的内容。ref
、out
还是什么都不使用,调用方法都会看到诸如someClass.Message = "Hello World"
之类的变化myFunction(someClass)
中写入someClass = new MyClass()
会替换someClass
在范围内看到的对象。仅 code>myFunction
方法。 调用方法仍然知道它创建并传递给您的方法的原始MyClass
实例您需要
ref
或out< /code> 如果您打算将
someClass
替换为一个全新的对象,并希望调用方法看到您的更改myFunction(out someClass)
中写入someClass = new MyClass()
会更改调用myFunction
的方法所看到的对象存在其他程序员
,他们想知道您将如何处理他们的数据。 想象一下您正在编写一个将被数百万开发人员使用的库。 您希望他们知道当他们调用您的方法时您将如何处理他们的变量
Using
ref
声明“当您调用我的方法时传递分配给某个值的变量。请注意,我可能会在我的方法过程中将其完全更改为其他内容,不要指望在我完成后您的变量会指向旧对象”Using
out
声明“将占位符变量传递给我的方法,它是否有值并不重要;编译器会强制我赋值;我绝对保证在调用我的方法之前,变量所指向的对象在我完成时会有所不同说一句,在 C#7.2 中,有一个
in 修饰符也是如此
,这可以防止该方法将传入的实例交换为不同的实例。 可以将其视为对数百万开发人员说“将您的原始变量引用传递给我,我保证不会将您精心制作的数据交换为其他内容”。
in
有一些特殊性,在某些情况下,例如可能需要隐式转换以使您的 Short 与in int
兼容,编译器将暂时生成 int,加宽你的不足之处,通过参考传递并完成。 它可以做到这一点,因为你已经声明你不会搞乱它。微软通过数字类型上的
.TryParse
方法做到了这一点:通过将参数标记为
out
,他们在这里主动声明“我们肯定将把您精心设计的值 98234957 更改为其他值”当然,对于解析值类型之类的事情,他们有点必须这样做,因为如果不允许解析方法将值类型交换为其他值,它就不会工作得很好..但是想象一下您正在创建的某个库中有一些虚构的方法:
您可以看到它是一个
out
,因此您可以知道如果您花几个小时处理数字,就会创建完美的方法SomeClass:嗯,那是浪费时间,花了那么多时间来上完美的课。 它肯定会被扔掉并被 PoorlyNamedMethod 取代
As well as allowing you to reassign someone else's variable to a different instance of a class, return multiple values etc, using
ref
orout
lets someone else know what you need from them and what you intend to do with the variable they provideYou don't need
ref
orout
if all you're going to do is modify things inside theMyClass
instance that is passed in the argumentsomeClass
.someClass.Message = "Hello World"
whether you useref
,out
or nothingsomeClass = new MyClass()
insidemyFunction(someClass)
swaps out the object seen by thesomeClass
in the scope of themyFunction
method only. The calling method still knows about the originalMyClass
instance it created and passed to your methodYou need
ref
orout
if you plan on swapping thesomeClass
out for a whole new object and want the calling method to see your changesomeClass = new MyClass()
insidemyFunction(out someClass)
changes the object seen by the method that calledmyFunction
Other programmers exist
And they want to know what you're going to do with their data. Imagine you're writing a library that will be used by millions of developers. You want them to know what you're going to do with their variables when they call your methods
Using
ref
makes a statement of "Pass a variable assigned to some value when you call my method. Be aware that I might change it out for something else entirely during the course of my method. Do not expect your variable to be pointing to the old object when I'm done"Using
out
makes a statement of "Pass a placeholder variable to my method. It doesn't matter whether it has a value or not; the compiler will force me to assign it to a new value. I absolutely guarantee that the object pointed to by your variable before you called my method, will be different by the time I'm doneBy the way, in C#7.2 there's an
in
modifier tooAnd that prevents the method from swapping out the passed in instance for a different instance. Think of it like saying to those millions of developers "pass me your original variable reference, and I promise not to swap your carefully crafted data out for something else".
in
has some peculiarities, and in some cases such as where an implicit conversion might be required to make your short compatible with anin int
the compiler will temporarily make an int, widen your short to it, pass it by reference and finish up. It can do this because you've declared you're not going to mess with it.Microsoft did this with the
.TryParse
methods on the numeric types:By flagging the parameter as
out
they're actively declaring here "we are definitely going to change your painstakingly crafted value of 98234957 out for something else"Of course, they kinda have to, for things like parsing value types because if the parse method wasn't allowed to swap out the value type for something else it wouldn't work very well.. But imagine there was some fictitious method in some library you're creating:
You can see it's an
out
, and you can thus know that if you spend hours crunching numbers, creating the perfect SomeClass:Well that was a waste of time, taking all those hours to make that perfect class. It's definitely going to be tossed away and replaced by PoorlyNamedMethod
ref 和 out 的工作方式就像 C++ 中的引用传递和指针传递一样。
对于 ref,必须声明并初始化参数。
对于 out,必须声明参数,但可能会也可能不会初始化
ref and out work just like passing by references and passing by pointers as in C++.
For ref, the argument must declared and initialized.
For out, the argument must declared but may or may not be initialized
创作时间:
(1) 我们创建调用方法
Main()
(2) 它创建一个 List 对象(这是一个引用类型对象)并将其存储在变量中
我的列表
。在运行时:
(3) 运行时在堆栈上的 #00 处分配一块内存,其宽度足以存储地址 (#00 =
myList
,因为变量名称实际上只是 (4) 运行时在堆上的内存位置 #FF 创建一个列表对象(所有这些地址都是为了举例)
(5) 然后运行时将对象的起始地址 #FF 存储在 #00(或用单词来说,将 List 对象的引用存储在指针
myList
中)返回创作时间:
(6) 然后我们将 List 对象作为参数传递
myParamList
到被调用方法modifyMyList
并为其分配一个新的 List 对象在运行时:
(7) 运行时启动被调用方法的调用例程,并作为其一部分检查参数类型。
(8) 找到引用类型后,它在#04 处的堆栈上分配一块内存,用于为参数变量
myParamList
别名。(9) 然后它也将值#FF 存储在其中。
(10)运行时在堆上的内存位置#004处创建一个列表对象,并用该值替换#04中的#FF(或者在该方法中取消引用原始List对象并指向新的List对象)
#00中的地址不是更改并保留对 #FF 的引用(或原始
myList
指针不受影响)。ref 关键字是一个编译器指令,用于跳过 (8) 和 (9) 的运行时代码的生成,这意味着方法参数不会进行堆分配。 它将使用原来的#00指针来操作#FF处的对象。 如果原始指针未初始化,运行时将停止抱怨它无法继续,因为变量未初始化
out 关键字是一个编译器指令,它几乎是与 ref 相同,但在 (9) 和 (10) 处略有修改。 编译器期望参数未初始化,并将继续执行 (8)、(4) 和 (5) 在堆上创建对象并将其起始地址存储在参数变量中。 不会抛出未初始化的错误,并且之前存储的任何引用都将丢失。
Authoring Time:
(1) We create the calling method
Main()
(2) it creates a List object (which is a reference type object) and stores it in the variable
myList
.During Runtime:
(3) Runtime allocates a memory on stack at #00, wide enough to store an address (#00 =
myList
, since variable names are really just aliases for memory locations)(4) Runtime creates a list object on heap at memory location #FF( all these addresses are for example sakes)
(5) Runtime would then store the starting address #FF of the object at #00(or in words, stores the reference of the List object in the pointer
myList
)Back to Authoring Time:
(6) We then pass the List object as argument
myParamList
to the called methodmodifyMyList
and assign a new List object to itDuring Runtime:
(7) Runtime starts the call routine for the called method and as part of it, checks the type of parameters.
(8) Upon finding the reference type, it allocates a memory on stack at #04 for aliasing the parameter variable
myParamList
.(9) It then stores the value #FF in it as well.
(10) Runtime creates a list object on heap at memory location #004 and replaces #FF in #04 with this value(or dereferenced the original List object and pointed to the new List object in this method)
The address in #00 is not altered and retains the reference to #FF(or the original
myList
pointer is not disturbed).The ref keyword is a compiler directive to skip the generation of runtime code for (8) and (9) which means there will be no heap allocation for method parameters. It will use the original #00 pointer to operate on the object at #FF. If the original pointer is not initialised, the runtime will halt complaining it can’t proceed since the variable isn’t initialised
The out keyword is a compiler directive which pretty much is the same as ref with a slight modification at (9) and (10). The compiler expects the argument to be uninitialised and will continue with (8), (4) and (5) to create an object on heap and to stores its starting address in the argument variable. No uninitialised error will be thrown and any previous reference stored will be lost.
为了说明许多出色的解释,我开发了以下控制台应用程序:
AppendWorld
:传递名为LiStri
的StringList
副本。 在该方法开始时,此副本引用原始列表并且
因此可用于修改此列表。 稍后的
LiStri
参考资料方法内的另一个
List
对象不影响原始列表。
HalloWelt
:LiStriRef
是已初始化的别名ListStringRef
。 传递的List
对象用于初始化新的,因此
ref
是必要的。CiaoMondo
:LiStriOut
是ListStringOut
的别名,并且必须是已初始化。
因此,如果一个方法只是修改传递变量引用的对象,编译器将不允许您使用
out
并且您不应该使用ref
因为它不会让编译器感到困惑但代码的读者。 如果该方法将使传递的参数引用另一个对象,请对已初始化的对象使用ref
,对必须为传递的参数初始化新对象的方法使用out
。 除此之外,ref
和out
的行为相同。To illustrate the many excellent explanations, I developed the following console app:
AppendWorld
: A copy ofStringList
namedLiStri
is passed. At thestart of the method, this copy references the original list and
therefore can be used to modify this list. Later
LiStri
referencesanother
List<string>
object inside the method which doesn't affectthe original list.
HalloWelt
:LiStriRef
is an alias of the already initializedListStringRef
. The passedList<string>
object is used to initialize anew one, therefore
ref
was necessary.CiaoMondo
:LiStriOut
is an alias ofListStringOut
and must beinitialized.
So, if a method just modifies the object referenced by the passed variable, the compiler will not let you use
out
and you should not useref
because it would confuse not the compiler but the reader of the code. If the method will make the passed argument reference another object, useref
for an already initialized object andout
for methods that must initialize a new object for the passed argument. Besides that,ref
andout
behave the same.它们几乎相同 - 唯一的区别是作为 out 参数传递的变量不需要初始化,并且使用 ref 参数的方法必须将其设置为某个值。
Ref 参数用于可能被修改的数据,out 参数用于作为已在使用某些内容的返回值的函数(例如 int.TryParse)的附加输出的数据。
They're pretty much the same - the only difference is that a variable you pass as an out parameter doesn't need to be initialised, and the method using the ref parameter has to set it to something.
Ref parameters are for data that might be modified, out parameters are for data that's an additional output for the function (eg int.TryParse) that are already using the return value for something.
参考:
ref 关键字用于将参数作为引用传递。 这意味着当方法中该参数的值发生更改时,它会反映在调用方法中。 使用 ref 关键字传递的参数必须在调用方法中初始化,然后再传递给被调用方法。
出去:
out 关键字也可以像 ref 关键字一样用于传递参数,但可以在不为其赋值的情况下传递参数。 使用 out 关键字传递的参数必须在返回到调用方法之前在被调用方法中初始化。
方法重载中的 Ref 和 out
方法重载中不能同时使用 ref 和 out。 但是,ref 和 out 在运行时的处理方式不同,但在编译时的处理方式相同(CLR 在为 ref 和 out 创建 IL 时并不区分两者)。
Ref:
The ref keyword is used to pass an argument as a reference. This means that when value of that parameter is changed in the method, it gets reflected in the calling method. An argument that is passed using a ref keyword must be initialized in the calling method before it is passed to the called method.
Out:
The out keyword is also used to pass an argument like ref keyword, but the argument can be passed without assigning any value to it. An argument that is passed using an out keyword must be initialized in the called method before it returns back to calling method.
Ref and out in method overloading
Both ref and out cannot be used in method overloading simultaneously. However, ref and out are treated differently at run-time but they are treated same at compile time (CLR doesn't differentiates between the two while it created IL for ref and out).
我想举两个主要区别:
ref
和out
通过引用传递,因此;但是:
与
out
相同。2.
ref
参数必须是可赋值的变量。嗯:
但是:
There 2 main difference that i want to give example for:
ref
andout
pass by reference, hense;but:
and same with
out
.2.
ref
argument must be an assignable variable.hense:
but:
下面我展示了一个同时使用 Ref 和 out 的示例。 现在,你们都将了解裁判和出局的情况。
在下面提到的示例中,当我评论 //myRefObj = new myClass { Name = "ref external called!! " };
行,会得到一个错误,指出“使用未分配的局部变量'myRefObj'”,但out中没有这样的错误。
在哪里使用 Ref:当我们使用 in 参数调用过程时,相同的参数将用于存储该过程的输出。
在哪里使用 Out:当我们调用一个没有 in 参数的过程时,并且相同的参数将用于从该过程返回值。
另请注意输出
Below I have shown an example using both Ref and out. Now, you all will be cleared about ref and out.
In below mentioned example when i comment //myRefObj = new myClass { Name = "ref outside called!! " };
line, will get an error saying "Use of unassigned local variable 'myRefObj'", but there is no such error in out.
Where to use Ref: when we are calling a procedure with an in parameter and the same parameter will be used to store the output of that proc.
Where to use Out: when we are calling a procedure with no in parameter and teh same param will be used to return the value from that proc.
Also note the output
你可以检查这个代码,它会向你描述它的完整区别
当您使用“ref”时,这意味着您已经初始化了该 int/string
但
当你使用“out”时
无论您是否初始化该 int/string,它都适用于两种情况
但你必须在该函数中初始化该 int/string
you can check this code it will describe you its complete differnce
when you use "ref" its mean that u already initialize that int/string
but
when you use "out"
it works in both conditions wheather u initialize that int/string or not
but u must initialize that int/string in that function
从接收参数的方法的角度来看,
ref
和out
之间的区别在于 C# 要求方法必须写入每个out
参数在返回之前,除了将其作为out
参数传递或对其进行写入之外,不得对此类参数执行任何操作,直到将其作为out
参数传递为止到另一种方法或直接写入。 请注意,其他一些语言没有强加这样的要求; 在 C# 中使用out
参数声明的虚拟或接口方法可以用另一种语言覆盖,该语言不会对此类参数施加任何特殊限制。从调用者的角度来看,C# 在许多情况下会假设调用带有
out
参数的方法时会导致传递的变量在未先读取的情况下被写入。 当调用用其他语言编写的方法时,这种假设可能不正确。 例如:如果
myDictionary
标识以 C# 以外的语言编写的IDictionary
实现,即使MyStruct s = new MyStruct(myDictionary);
看起来像一个赋值,它可能会使s
保持不变。请注意,与 C# 中的构造函数不同,VB.NET 中编写的构造函数不会假设调用的方法是否会修改任何
out
参数,并无条件清除所有字段。 完全用 VB 或完全用 C# 编写的代码不会发生上面提到的奇怪行为,但当用 C# 编写的代码调用用 VB.NET 编写的方法时,可能会发生。From the standpoint of a method which receives a parameter, the difference between
ref
andout
is that C# requires that methods must write to everyout
parameter before returning, and must not do anything with such a parameter, other than passing it as anout
parameter or writing to it, until it has been either passed as anout
parameter to another method or written directly. Note that some other languages do not impose such requirements; a virtual or interface method which is declared in C# with anout
parameter may be overridden in another language which does not impose any special restrictions on such parameters.From the standpoint of the caller, C# will in many circumstances assume when calling a method with an
out
parameter will cause the passed variable to be written without having been read first. This assumption may not be correct when calling methods written in other languages. For example:If
myDictionary
identifies anIDictionary<TKey,TValue>
implementation written in a language other than C#, even thoughMyStruct s = new MyStruct(myDictionary);
looks like an assignment, it could potentially leaves
unmodified.Note that constructors written in VB.NET, unlike those in C#, make no assumptions about whether called methods will modify any
out
parameters, and clear out all fields unconditionally. The odd behavior alluded to above won't occur with code written entirely in VB or entirely in C#, but can occur when code written in C# calls a method written in VB.NET.如果你想将你的参数作为引用传递,那么你应该在将参数传递给函数之前初始化它,否则编译器本身会显示错误。但是如果是 out 参数,你不需要在将对象参数传递给函数之前初始化它。方法。您可以在调用方法本身中初始化对象。
If you want to pass your parameter as a ref then you should initialize it before passing parameter to the function else compiler itself will show the error.But in case of out parameter you don't need to initialize the object parameter before passing it to the method.You can initialize the object in the calling method itself.
迟到的答复,但想到发帖。 可能比其他答案更清楚一些。
ref 关键字:
ref 是一个关键字,用于通过引用传递任何值(进一步了解编程中的按值调用和按引用调用)。 简而言之,您声明并初始化一个值,例如让我们说
intage = 5;
,因此该年龄通过保留 4 个字节的位置保存在内存中。 现在,如果您使用 ref 将这个年龄变量传递给另一个方法(这意味着通过引用而不是通过值传递它们),那么编译器将只传递该变量的引用,或者明确地说,是变量所在位置的内存地址被存储,被调用的方法接收该地址并直接访问该地址中的数据。 显然,对该数据的任何更改也会发生在调用方法中存在的变量上。Out 关键字:
Out 和 in 类似于它们都传递变量的引用。 现在我们知道两者都需要传递变量的引用,很明显,内存中必须存在一个位置来保存变量的字节。 但在 out 的情况下不会初始化。 因为要求是,被调用的方法必须初始化该值并返回它。
In 关键字:
现在 in 关键字的工作方式与 ref 关键字完全相同,只有一个条件,即不得修改作为引用传递的值。
MSDN 参考文献:
希望以上内容清楚。
Late answer, but thought of posting. May be a bit more clear than the other answers.
ref keyword:
ref is a keyword which is used to pass any value by reference(refer to call by value and call by reference in programming for further knowledge). In short, you declare and initialize a value for example let us say
int age = 5;
so this age is saved in the memory by holding a place of 4 bytes. Now if you are passing this age variable to another method with ref (which means passing them by reference and not by value) then the compiler will just pass the reference of that variable or in clear terms, the memory address of the place where the variable is stored and the called method receives this address and directly accesses the data in that address. So obviously any change to that data will happen also to the variable present in the calling method.Out keyword:
Out and in are similar to that where they both pass the reference of the variable. Now we know that both need to pass the reference of the variable, it is very clear that there must be a place in memory existing that holds the bytes for the variable. But not initalized in case of out. Becuase the requirement is that, the called method must initialize the value and return it.
In keyword:
Now in keyword works exactly the same as ref keyword with only one condition that, the value being passed as reference must not be modified.
MSDN References:
Hope the above is clear.
请注意,在函数内部传递的引用参数是直接起作用的。
例如,
这将写为 Dog,而不是 Cat。 因此你应该直接处理 someObject。
Mind well that the reference parameter which is passed inside the function is directly worked on.
For example,
This will write Dog, not Cat. Hence you should directly work on someObject.
我可能不太擅长这一点,但是字符串(即使它们在技术上是引用类型并且存在于堆上)肯定是按值传递的,而不是引用传递的?
这就是为什么如果您希望更改存在于进行更改的函数范围之外,则需要 ref,否则您不会传递引用。
据我所知,您只需要 ref 来表示结构/值类型和字符串本身,因为字符串是一种引用类型,它假装它是但不是值类型。
不过,我可能完全错了,我是新人。
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?
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.
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.
I could be completely wrong here though, I am new.