我正在创建一个函数,我需要传递一个对象,以便它可以被函数修改。有什么区别:

public void myFunction(ref MyClass someClass)

and

public void myFunction(out MyClass someClass)

我应该用哪个,为什么?


当前回答

裁判上场又出局。

您应该优先使用out,只要它能满足您的需求。

其他回答

它们几乎是一样的——唯一的区别是,作为out形参传递的变量不需要初始化,使用ref形参的方法必须将其设置为某个值。

int x;    Foo(out x); // OK 
int y;    Foo(ref y); // Error

Ref形参用于可能被修改的数据,out形参用于已经使用返回值的函数(例如int.TryParse)的额外输出数据。

裁判上场又出局。

您应该优先使用out,只要它能满足您的需求。

注意,在函数内部传递的引用参数是直接处理的。

例如,

    public class MyClass
    {
        public string Name { get; set; }
    }

    public void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog".
    }

    public void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

这会写狗,而不是猫。因此,您应该直接在someObject上工作。

裁判: ref关键字用于将参数作为引用传递。这意味着当该参数的值在方法中被更改时,它会反映在调用方法中。使用ref关键字传递的参数在传递给被调用方法之前必须在调用方法中初始化。

: out关键字也用于传递一个参数,如ref关键字,但参数可以在不给它赋值的情况下传递。使用out关键字传递的参数在返回调用方法之前必须在被调用方法中初始化。

public class Example
{
 public static void Main() 
 {
 int val1 = 0; //must be initialized 
 int val2; //optional

 Example1(ref val1);
 Console.WriteLine(val1); 

 Example2(out val2);
 Console.WriteLine(val2); 
 }

 static void Example1(ref int value) 
 {
 value = 1;
 }
 static void Example2(out int value) 
 {
 value = 2; 
 }
}

/* Output     1     2     

在方法重载中引用和out

ref和out不能同时用于方法重载。然而,ref和out在运行时的处理方式不同,但在编译时的处理方式相同(CLR在为ref和out创建IL时不区分两者)。

: return语句只能用于从函数中返回一个值。但是,使用输出参数,可以从一个函数返回两个值。输出参数类似于引用参数,只是它们将数据传输出方法而不是传输到方法中。

下面的例子说明了这一点:

using System;

namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void getValue(out int x )
      {
         int temp = 5;
         x = temp;
      }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;

         Console.WriteLine("Before method call, value of a : {0}", a);

         /* calling a function to get the value */
         n.getValue(out a);

         Console.WriteLine("After method call, value of a : {0}", a);
         Console.ReadLine();

      }
   }
}

裁判: 引用形参是对变量内存位置的引用。与值参数不同,通过引用传递参数时,不会为这些参数创建新的存储位置。引用参数表示与提供给方法的实际参数相同的内存位置。

在c#中,使用ref关键字声明引用参数。下面的例子说明了这一点:

using System;
namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void swap(ref int x, ref int y)
      {
         int temp;

         temp = x; /* save the value of x */
         x = y;   /* put y into x */
         y = temp; /* put temp into y */
       }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;
         int b = 200;

         Console.WriteLine("Before swap, value of a : {0}", a);
         Console.WriteLine("Before swap, value of b : {0}", b);

         /* calling a function to swap the values */
         n.swap(ref a, ref b);

         Console.WriteLine("After swap, value of a : {0}", a);
         Console.WriteLine("After swap, value of b : {0}", b);

         Console.ReadLine();

      }
   }
}