【发布时间】:2009-08-22 22:04:54
【问题描述】:
使用关键字ref时,调用代码需要初始化传递的参数,但使用关键字out我们不需要这样做。
- 我们为什么不到处使用
out? - 两者之间的确切区别是什么?
- 请举例说明我们需要使用
ref而不能使用out的情况?
【问题讨论】:
-
我认为
ref表示in和out。
标签: c#
使用关键字ref时,调用代码需要初始化传递的参数,但使用关键字out我们不需要这样做。
out?ref而不能使用out的情况?【问题讨论】:
ref 表示in 和out。
标签: c#
这个MSDN article给出了答案。从那个帖子:
两种传参方式 由
out和ref解决的问题很巧妙 不同,但是它们都非常 常见的。之间的细微差别 这些模式导致一些非常常见的 编程错误。其中包括:
- 没有给
out赋值 所有控制流路径中的参数- 不给变量赋值 用作
ref参数因为 C# 语言分配 不同的明确分配规则 这些不同的参数传递 模式,这些常见的编码错误是 被编译器捕获为 不正确的 C# 代码。
决定包括
ref和out参数传递 模式是允许编译器 检测这些常见的编码错误 值得额外的复杂性 同时具有ref和out参数 语言中的传递模式。
【讨论】:
out 是ref 的一种特殊形式,其中引用的内存不应在调用之前初始化。
在这种情况下,C# 编译器强制在方法返回之前分配 out 变量,并且在分配之前不使用该变量。
out 不起作用但 ref 起作用的两个示例:
void NoOp(out int value) // value must be assigned before method returns
{
}
void Increment(out int value) // value cannot be used before it has been assigned
{
value = value + 1;
}
【讨论】:
ref 参数传递给方法之前对其进行初始化。它可以使out 参数未初始化。在方法调用语句之后会被认为已初始化。
这些答案都不让我满意,所以这是我对 ref 与 out 的看法。
我的回答是以下两页的总结:
比较
ref/out关键字out 或ref 传递,因为属性实际上是方法ref / out 在编译时不被视为方法签名的一部分,因此如果方法之间的唯一区别是其中一个方法采用 ref 参数而另一个采用 @ 参数,则方法不能重载987654335@论据对比
ref
out
示例
不会编译,因为方法签名的唯一区别是 ref / out:
public void Add(out int i) { }
public void Add(ref int i) { }
使用ref关键字:
public void PrintNames(List<string> names)
{
int index = 0; // initialize first (#1)
foreach(string name in names)
{
IncrementIndex(ref index);
Console.WriteLine(index.ToString() + ". " + name);
}
}
public void IncrementIndex(ref int index)
{
index++; // initial value was passed in (#2)
}
使用out关键字:
public void PrintNames(List<string> names)
{
foreach(string name in names)
{
int index; // not initialized (#1)
GetIndex(out index);
Console.WriteLine(index.ToString() + ". " + name);
}
}
public void GetIndex(out int index)
{
index = IndexHelper.GetLatestIndex(); // needs to be assigned a value (#2 & #3)
}
作者随笔
out关键字的概念类似于使用ParameterDirection的Output枚举值在ADO.NET中声明输出参数ref 关键字例子:
public void ReassignArray(ref int[] array)
{
array = new int[10]; // now the array in the calling code
// will point to this new object
}
有关引用类型与值类型的更多信息,请参阅Passing Reference-Type Parameters (C# Programming Guide)
【讨论】:
当你需要使用 ref 而不是 out 时,一个人为的例子如下:
public void SquareThisNumber(ref int number)
{
number = number * number;
}
int number = 4;
SquareThisNumber(ref number);
这里我们希望number 是一个输入输出变量,所以我们使用ref。如果我们使用了out,编译器会给出一个错误,说我们在使用它之前初始化了一个out 参数。
【讨论】:
ref 关键字允许您更改参数的值。被调用的方法可以是调用链中的一个中间环节。使用 out 关键字的方法只能在调用链的开头使用。
另一个优点是现有值可以在方法的逻辑中使用,并且仍然保存返回值。
在 Oracle 中,函数具有显式的 IN(默认值以及不设置方向时得到的结果)IN/OUT 和 OUT 参数。等价的是 normal(只是参数)、ref [参数] 和 out [参数]。
【讨论】:
编译器知道在调用之前不应该设置 out 变量。这允许它们在使用前被声明。但是它知道它必须在它用于返回的函数之前设置。
【讨论】:
当我们在调用以out 关键字为前缀的方法时传递值时,它会完全不同地对待它,就像我们没有将它传递给方法一样。相反,我们实际上是从方法的定义部分将 out 变量的值收集(输出)到我们调用该方法的方法 out 变量参数。
所以out variable是方法定义中处理完成的输出,这就是为什么我们需要创建它,初始化它,只在定义中修改它。
当我们需要从特定方法返回多个值时,使用out 变量。
在ref 变量的情况下,我们需要先初始化它,因为它的内存位置作为参数传输到方法定义。想想如果我们在通过之前不对其进行初始化会发生什么?
【讨论】: