使用参考出关键词,与通过参考和传递的价值在C#
-
18-09-2019 - |
题
这里是我的了解迄今为止:
通过价值
传递的价值意味着一个复制的一个论点是通过。更改,不改变原来的。
通过参考
通过参考意味着一种参考原先是通过。更改基准的影响。
REF关键字
REF告诉编译器,对象是初始化之前进入功能。REF装置的价值已经设定,该方法,因此可以阅读和修改。REF两种方式,无论是在外。
出关键字
出去告诉编译器的对象将是intialized内部的功能。出装置的价值是不是已经设定,因此必须设置之后才返回。是只有一个办法,这是出。
的问题
因此,在什么情况下你会相结合使用的参考和出了关键词,与通过参考或通过价值?例将极大地帮助。
帮助极大的赞赏。
解决方案
您会绝不会 1个参数结合ref
和out
。他们都意味着“通过引用传递”。
可以当然结合在一种方法ref参数和输出参数。
和ref
out
之间的区别主要在于的意图即可。 REF信号的2路数据传输,出装置1的方法。
但是,除了意图,C#编译器跟踪明确指派和,使最值得注意的区别。它还可以防止out参数的误用(读出)。
void SetOne(out int x)
{
int y = x + 1; // error, 'x' not definitely assigned.
x = 1; // mandatory to assign something
}
void AddTwo(ref int x)
{
x = x + 2; // OK, x is known to be assigned
}
void Main()
{
int foo, bar;
SetOne(out foo); // OK, foo does not have to be assigned
AddTwo(ref foo); // OK, foo assigned by SetOne
AddTwo(ref bar); // error, bar is unassigned
}
其他提示
帮助不胜感激
您理解将通过正确和谨慎地使用语言的改善。
传由值表示的参数的副本被传递。
是,这正是准确。
更改该副本不改变原始
不完全。由值和变量之间小心区分开始。考虑:
class Foo { public int x; }
...
void N()
{
Foo blah = new Foo();
blah.x = 0;
M(blah);
}
...
void M(Foo foo)
{
foo.x = 123; // changes blah.x
foo = null; // does not change blah
}
这里的变量是x,等等和Foo。 x是一个场,胡说是本地人,foo是一个正式的参数。
这里的值是NULL,0,123,和foo的实例的引用。的即参考是一个值。根据理解这个事实是至关重要的。
嗒嗒的值的副本通过复制变量等等的值存入变量foo的通过。等等的值是foo的实例的引用。
M可改变变量x的值,因为M具有嗒嗒的值,这是一个Foo基准的副本。当M改变foo的内容为空,不改变等等; FOO包含嗒嗒的值的副本。
通过引用传递装置将原始的引用传递。
仔细选择您的措辞。什么是 “原”?
这将得到更好的表述为“通过引用意味着,参考参数,它必须是一个变量,传递”。想它更简单的方法是,“通过参考使得参数作为参数传递的变量的别名”。
改变到参考影响原始
由于参数和参数是互为别名,它不是变化到参考影响原始;基准是原始。它们都相同的变量
REF告诉该对象进入函数之前初始化的编译器。
“对象”是没有意义的。你的意思是 “可变”。
“REF”不“告诉该变量被初始化编译器”。相反,“裁判”告诉编译器“你,编译器,必须确认变量初始化”。这是相当不同!
REF装置的值已被设置,
没有,REF要求的可变已经设置。有没有这样的东西“设定值”。
该方法可因此读取它并修改它。
通过在哪里 “它” 你的意思是 “可变”。
REF为两种方式,无论是在进出。
正确。
OUT告诉该对象将在函数内部被intialized编译器。
停止使用“对象”来表示“变量”。如果你停止混淆完全不同的东西,你会明白的事情更清楚。 变量不是对象。变量是的存储地点其中的一些可能包含的值,并且其中一些值可能是对对象的引用
所以,走出告诉变量将在方法内部进行初始化,是编译器,但是这并不完全正确。您忘记了的情况下,该方法将抛出一个异常,或方法将进入一个无限循环 - 这些都是同样的法律情形。
出装置的值尚未设置,
再次由“值”,就意味着“变量”。但是,这是不准确的。这是完全合法的传递一个初始化的变量作为“out”参数。无意义,但合法的。
和因此必须在调用返回之前被设置。
“返回”不叫;方法被调用。但是,是的,这个方法必须为其赋值RETURNI前变量纳克正常。
OUT是只有一种方式,这是进行。
右。
因此,在什么情况下,您将结合使用ref和out关键字
有没有这样的情形。
你了解该动态的通过两种方式。一些参数的情况可能是:
ref int num
对于一个入/输出参数。功能 可 修改的价值所在。out int num
像ref除功能必须分配一个值,它之前返回。
在大输出参数的良好时的功能必须返回多价值,因为一个功能,只有一个返回值(虽然它可以化合物)。
有时数据接入提供商,如一些ADO.NET 方法中,使用输出参数的提供信息反馈。一些数据访问方法的模拟数据库存储程序的具有进/出参数。
编辑: 一个规定为准类型参数 ref StringBuilder word
或 StringBuilder word
(价值)的行为相同的-的串外受到影响,虽然潜在的implementatoin可能略有不同,因为那时的重点是基准而不是价值上堆。
编辑: 我已经纠正了这个答案,以反映出关键字在C#不做什么你可能希望它的(例如一个真正的出参数的计算机科学意义的术语)。我原先指出,'退出'是通过价值,但被证明是错误的。
你不可能用'出"和"参考'在一起。有三个叫公约在C#(净框架):
- 没有关键字=通过由的价值(在)
- '退出'Keyword=通过参考(REF)没有明确分配的要求之前呼叫
- 'ref'Keyword=通过参考(REF)明确分配的要求之前呼叫
C#没有真实的或在出参数的能力。
看到了'参数在C#是不是真的出参数,可以使用下列代码:
public class Test
{
Action _showValue;
public void Run()
{
string local = "Initial";
_showValue = () => { Console.WriteLine(local.ToString()); };
Console.WriteLine("Passing by value");
inMethod(local);
Console.WriteLine("Passing by reference with 'out' keyword");
outMethod(out local);
Console.WriteLine("Passing by reference with 'ref' keyword");
refMethod(ref local);
}
void inMethod(string arg)
{
_showValue();
arg = "IN";
_showValue();
}
void outMethod(out string arg)
{
_showValue();
arg = "OUT";
_showValue();
}
void refMethod(ref string arg)
{
_showValue();
arg = "REF";
_showValue();
}
}
输出为:
Passing by value
Initial
Initial
Passing by reference with 'out' keyword
Initial
OUT
Passing by reference with 'ref' keyword
OUT
REF
正如你可以看到,这两个'退出'和'ref'实际上是通过参考。唯一的区别是,在编译器是如何对待他们明确分配的目的。
使用OUT
关键字如果有需要返回多于一个值的方法是有用的。例如,看像int.TryParse()
方法。
使用REF
是更的对象的明确性。请记住,任何非原始传递给方法本质上是通过引用传递有没有很多必要为它在正常托管代码的。通过声明ref关键字你,说明该参数将有可能在方法体进行修改,从而调用代码应该知道它(因此为什么你必须明确地加在调用代码中ref
以及
如果你了解C ++也许这将帮助你:
void Foo(Bar) {} // pass by value c# (if it's a value type ;))
void Foo(Bar) {} // c++
void Foo(Bar) {} // pass by reference c# (if it's a reference type ;))
void Foo(Bar&) {} // c++
void Foo(ref Bar) {} // c#
void Foo(Bar*) // c++
void Foo(out Bar) {} // c#
void Foo(Bar**) {} // c++ (the contents of *Bar needs to be filled up)
您路过你想阅读和其他功能的书面裁判的东西,所以你应该通过以初始化的变量被正确读取。
编辑:例如:
void mymethod(ref int a) {
a++;
}
您传递要由另一个功能被写成了一些东西,但你并不需要初始化它,因为它不会被函数读取,只写了。
编辑:例如:
void mymethod2(out string a) {
a="hello";
}