【问题标题】:Using out keyword in c#在 C# 中使用 out 关键字
【发布时间】:2011-12-04 17:21:17
【问题描述】:

谁能建议我确切地使用 out 关键字作为参数,以及它如何连接以从函数返回多个值,就像在这个 POST 中一样,我对 out 变量和普通变量感到困惑。谁能帮我解决这个问题。

【问题讨论】:

标签: c# .net keyword out


【解决方案1】:

这经常令人困惑,我认为 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;

引用或输出参数为现有变量创建别名。当你说

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;

q 和x 是两个不同的名称,它们引用同一个变量。递增q 也会递增x,因为它们是相同的。上例中的z 和x 是两个不同的名称,它们引用两个不同的变量。递增z 不会改变x。

总结一下:“out”和“ref”只是表示“不要创建新变量;而是暂时为现有变量创建第二个名称”。

现在清楚了吗?

更新:我没有说“out”和“ref”之间的区别是什么。区别很简单。在“调用者”方面,“ref”必须是在调用方法之前明确分配的变量。不需要“出局”。在“被调用者”端,“ref”可能在写入之前被读取,但“out”必须在读取之前写入。此外,必须在控制正常离开方法之前写入“out”。

【讨论】:

  • 不是,我创建了一个示例示例项目,我在方法 static void N(out int q) { q = q + 1;现在它抛出错误说使用未分配的局部变量 q,现在如何分配,我已经为 q 赋值。
  • out 参数不需要在调用站点之前在调用者中明确分配。因此,必须在被调用方(声明方法)中首次使用之前对其进行分配。您可以通过将 out 更改为 ref 来更正评论中的方法。
  • @Abbas:你是对的;我不清楚,因为我没有说“out”和“ref”之间有什么区别。现在更新清楚了吗?
【解决方案2】:

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

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
    }
}

【讨论】:

  • 还有另一个重要因素。 out参数必须在方法正常返回前明确赋值。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    out 关键字应在您想要: a)允许您的函数从调用代码堆栈修改特定变量和 b) 强制在你的函数中设置这个变量值

    【讨论】:

      【解决方案5】:

      MSDN 总是一个很好的起点

      【讨论】:

        【解决方案6】:

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

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

        通过引用本质上为方法提供了数据的内存地址,因此如果方法修改数据,它会更改原始数据。

        Out是一种特殊类型的ref,调用方法前不需要初始化变量,传入null即可调用,必须由方法设置。

        您可以想到的另一种方式(从外部代码的角度)是:

        val = 只读

        ref = 读/写

        out = 只写。

        【讨论】:

        • Out 参数不是“只写”。如果它们是,那将非常方便,我同意,但它们不是,并且希望事实并非如此。 “out”参数的限制是它们必须在读取之前写入,而不是绝对不能读取。在写入后从 out 参数读取是完全合法的。正是这个特性使得以逆变方式处理 out 参数是非法的,就像返回的类型一样。
        • @Eric:我希望你的意思是说“协变方式”,否则我必须重读我的书和你关于协变/逆变的系列(好像 Action >> 并没有让我的头失控,哈)。
        • @Alan:哎呀,你当然是对的。正常的“in”参数可以是逆变的。如果输出参数实际上是只写的,则它们可能是协变的,但它们不是。
        • @Eric Lippert,我确实说过这只是一种可能的思考方式,并且我还指定从外部代码的角度来看。最后一段旨在为预期用途提供一个简单的概念模型,而不是绝对准确。
        • @stevenrcfox 有趣的方式来看待它。为了完整起见,您还应该添加“in”关键字。
        【解决方案7】:

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

        out 关键字很好,如果您想返回多个预定义类型的值(例如 int、List<string> 和 DateTime),并且您不想创建新的上课只是为了这个目的。

        【讨论】:

          【解决方案8】:

          好的,

          让我们看看这种函数的常用模式 - 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# 将上述模式解释为自身会产生这样一个元组。

          【讨论】:

            猜你喜欢
            • 2017-09-02
            • 1970-01-01
            • 2020-04-23
            • 1970-01-01
            • 2014-03-30
            • 2018-11-15
            • 2013-12-10
            • 1970-01-01
            • 2011-02-17
            相关资源
            最近更新 更多