【问题标题】:What do ref, val and out mean on method parameters?ref、val 和 out 对方法参数的含义是什么?
【发布时间】:2010-09-05 23:56:54
【问题描述】:

我正在寻找一个清晰、简洁和准确的答案。

理想情况下作为实际答案,尽管欢迎提供良好解释的链接。

这也适用于 VB.Net,但关键字不同 - ByRefByVal

【问题讨论】:

    标签: c# .net vb.net


    【解决方案1】:

    关于 ref 与 out 的附加说明:两者之间的区别由 C# 编译器强制执行。 CLR 不区分 out 和 ref。这意味着您不能有两个方法的签名仅相差一个 out 或 ref

    void foo(int value) {}
    
    // Only one of the following would be allowed
    
    // valid to overload with ref
    void foo(ref int value) {}
    
    // OR with out
    void foo(out int value) {}
    

    【讨论】:

      【解决方案2】:

      默认情况下(在 C# 中),将对象传递给函数实际上会将引用的副本传递给该对象。更改参数本身只会更改参数中的值,而不是指定的变量。

      void Test1(string param)
      {
          param = "new value";
      }
      
      string s1 = "initial value";
      Test1(s1);
      // s1 == "initial value"
      

      使用outref 传递对函数调用中指定的变量的引用。对outref 参数值的任何更改都将传回给调用者。

      outref 的行为相同,除了一点点不同:ref 参数需要在调用之前初始化,而 out 参数可以不初始化。通过扩展,ref 参数保证在方法开始时被初始化,而out 参数被视为未初始化。

      void Test2(ref string param)
      {
          param = "new value";
      }
      
      void Test3(out string param)
      {
          // Use of param here will not compile
          param = "another value";
      }
      
      string s2 = "initial value";
      string s3;
      Test2(ref s2);
      // s2 == "new value"
      // Test2(ref s3); // Passing ref s3 will not compile
      Test3(out s2);
      // s2 == "another value"
      Test3(out s3);
      // s3 == "another value"
      

      编辑:正如dp 指出的那样,outref 之间的区别仅由 C# 编译器强制执行,而不是由 CLR 强制执行。据我所知,VB 没有out 的等价物,仅实现ref(如ByRef),与CLR 的支持相匹配。

      【讨论】:

      • “对该对象的引用的副本”或“对该对象的副本的引用”?
      【解决方案3】:

      我自己在 stackoverflow 上的一个问题也处理了这个话题。
      它以不同类型的语言处理"pass by reference" and "pass by value"c# is included,所以也许你也可以在那里找到一些额外的信息。

      基本上归结为:

      • ref:带有ref关键字的参数将通过引用传递
      • out:带有out关键字的参数将被视为输出参数

      但这确实是你能给出的最基本的答案,因为它比这里所说的要复杂一些

      【讨论】:

        【解决方案4】:

        out表示参数会被方法初始化:

        int result; //not initialised
        
        if( int.TryParse( "123", out result ) )
           //result is now 123
        else
           //if TryParse failed result has still be 
           // initialised to its default value (0)
        

        ref 将强制传递底层引用:

        void ChangeMyClass1( MyClass input ) {
           input.MyProperty = "changed by 1";
           input = null;
           //can't see input anymore ... 
           // I've only nulled my local scope's reference
        }
        
        void ChangeMyClass2( ref MyClass input ) {
           input.MyProperty = "changed by 2";
           input = null;
           //the passed reference is now null too.
        }
        
        MyClass tester = new MyClass { MyProperty = "initial value" };
        
        ChangeMyClass1( tester );
        // now tester.MyProperty is "changed by 1"
        
        ChangeMyClass2( ref tester );
        // now tester is null
        

        【讨论】:

          猜你喜欢
          • 2021-07-03
          • 1970-01-01
          • 2013-03-16
          • 2011-07-26
          • 2010-11-03
          • 2020-01-05
          • 2012-08-08
          • 1970-01-01
          相关资源
          最近更新 更多