在c#中使用out关键字

本文关键字:out 关键字 | 更新日期: 2023-09-27 18:11:04

谁能建议我确切使用out关键字作为参数,以及它如何连接从函数返回多个值,就像在这个POST中一样,我与正常变量的out变量混淆了。有谁能帮我一下吗?

在c#中使用out关键字

这经常令人困惑,我认为MSDN文档实际上有点"只有在已经知道的情况下才清楚"。也就是说,它是正确的,但只有当你已经理解了这个概念时,它才真正有意义。

我是这样想的。

常规形参对实参进行复制。当你说:

static int M(int z) { z = z + 1; return z; }    
...
int x = 123;
int y = M(x);

就像你说的:

int x = 123;
int z = x; // make a copy of x
z = z + 1;
int y = z;

ref out参数为现有变量创建别名。当你说

static void N(ref int q) { q = q + 1; }    
...
int x = 123;
N(x);

这就等于说:

int x = 123;
// MAGIC: q is now an another name for variable x
q = q + 1;

qx两个不同的名称,它们指的是同一个变量。增加q也会增加x,因为它们是相同的。前面示例中的zx两个不同的名称,它们引用两个不同的变量。增加z不改变x

总结:"out"answers"ref"的意思是"不创建一个新变量;而是暂时为现有的变量取第二个名字。

现在清楚了吗?

更新:我没有说"out"answers"ref"的区别是什么。区别很简单。在"调用方"方面,在调用方法之前,"ref"必须是一个明确赋值的变量。而"out"则不必如此。在"被调用者"一方,"ref"可以在被写入之前被读取,但"out"必须在被读取之前被写入。此外,必须在控件正常离开方法之前写入"out"。

MSDN文档已经很好地解释了这一点:

out关键字导致参数通过引用传递。这是类似于ref关键字,不同之处在于ref要求变量在传递之前进行初始化。若要使用out参数,则方法定义和调用方法必须显式地使用out关键字。例如:

class OutExample
{
    static void Method(out int i)
    {
        i = 44;
    }
    static void Main()
    {
        int value;
        Method(out value);
        // value is now 44
    }
}

它经常用于"尝试"获取值的模式中,例如:

int result;
if(Int32.TryParse("123", out result))
{
   Console.WriteLine(result + 1);
}

out关键字应在以下情况下使用:a)允许你的函数通过调用代码栈AND来修改特定的变量B)强制在函数中设置这个变量值

MSDN总是一个开始的好地方

在包括c#在内的大多数语言中,您可以通过两种方式传递值,通过值,通过引用。

按值为方法提供数据的副本,因此更改数据不会对原始数据产生任何影响

通过引用实际上给方法提供了数据的内存地址,因此如果方法修改数据,它将改变原始数据。

Out是ref的一种特殊类型,因为你不需要在调用方法之前初始化变量,它可以在传入null的情况下调用。并且必须由方法设置。

另一种考虑它的方式(从外部代码的角度)是:

val =只读

ref = read/write

out = write only

http://msdn.microsoft.com/en-us/library/t3c3bfhx(v=vs.80).aspx

如果您想要返回预定义类型的多个值(例如intList<string>DateTime),那么

out关键字是很好的,并且您不想为此目的创建一个新类。

Ok,

让我们看看这类函数的通常模式——TrySomething。假设你有一个函数,它可能会成功地给你一个值,但你不想为此使用异常,因为你不想要额外的开销,或者它是一个共同的特征。然后,如果方法成功,通常返回true,如果失败,则返回false。但是你会把你的输出值放在哪里呢?

一个可能的答案是使用像这样的out参数:

bool TrySomething(MyInputType input, out MyOutputType output)
{
   output = default(MyOutputType);
   /* ... Try getting the answer ... */
   if (!successful)
      return false;
   output = successfulOutput;
   return true;
}

备注:或者您可以考虑使用Tuple<bool,MyOutputType>,实际上f#会将上面的模式解释为自己产生这样的元组。