'ref' 和 'out' 关键字有什么区别?

public void myFunction(ref MyClass someClass)
public void myFunction(out MyClass someClass)

答案

ref告诉编译器在进入函数之前该对象已初始化,而out告诉编译器该对象将在函数内进行初始化。

因此,当ref是双向的时, out是仅输出的。

ref修饰符表示:

  1. 该值已设置并且
  2. 该方法可以读取和修改它。

out修饰符表示:

  1. 值未设置,在设置之前无法被方法读取。
  2. 该方法必须在返回之前进行设置。

假设 Dom 出现在 Peter 的小隔间中,了解有关 TPS 报告的备忘录。

如果 Dom 是裁判的论点,他将拥有备忘录的印刷版。

如果 Dom 提出异议,他将让 Peter 打印一份备忘录的新副本,以供他随身携带。

我将尝试解释一下:

我认为我们了解值类型的运作方式正确吗?值类型为(int,long,struct 等)。当您将它们发送给没有 ref 命令的函数时,它将复制数据 。您对函数中的数据所做的任何操作只会影响副本,而不会影响原始副本。 ref 命令发送 ACTUAL 数据,任何更改都会影响该功能之外的数据。

好了,让我们困惑的部分是引用类型:

让我们创建一个引用类型:

List<string> someobject = new List<string>()

当您新建someobject 时 ,将创建两个部分:

  1. 存储某个对象数据的内存块。
  2. 该数据块的引用(指针)。

现在,当你在someobject送入方法没有裁判它复制引用指针,而不是数据。因此,您现在有了:

(outside method) reference1 => someobject
(inside method)  reference2 => someobject

两个引用指向同一对象。如果您在使用给定 2 修改someobject属性会影响通过参考量都指向同一数据。

(inside method)  reference2.Add("SomeString");
 (outside method) reference1[0] == "SomeString"   //this is true

如果您将 reference2 无效或将其指向新数据,则不会影响 reference1 或数据 reference1 指向的数据。

(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true

The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject

现在,当你someobject发送通过裁判的方法会发生什么?对某个对象实际引用将发送到该方法。因此,您现在只有一个对数据的引用:

(outside method) reference1 => someobject;
(inside method)  reference1 => someobject;

但是,这是什么意思?它的行为与不通过 ref 发送某些对象完全相同,但有两个主要方面:

1)当您将方法内的引用无效时,它将使方法外的引用无效。

(inside method)  reference1 = null;
 (outside method) reference1 == null;  //true

2)现在,您可以将引用指向完全不同的数据位置,并且函数外部的引用现在将指向新的数据位置。

(inside method)  reference1 = new List<string>();
 (outside method) reference1.Count == 0; //this is true

裁判是进出

您应该使用out的地方就足够了您的需求优先。

出:

在 C#中,方法只能返回一个值。如果您想返回多个值,则可以使用 out 关键字。 out 修饰符 return 作为按引用返回。最简单的答案是关键字 “out” 用于从方法中获取值。

  1. 您无需在调用函数中初始化值。
  2. 您必须在调用的函数中分配该值,否则编译器将报告错误。

参考:

在 C#中,当您将值类型(例如 int,float,double 等)作为方法参数的参数传递时,它将按值传递。因此,如果修改参数值,它不会影响方法调用中的参数。但是,如果使用 “ref” 关键字标记该参数,它将反映在实际变量中。

  1. 您需要在调用函数之前初始化变量。
  2. 在方法中不必将任何值分配给 ref 参数。如果您不更改值,则需要将其标记为 “ref” 吗?

扩展 “狗,猫” 示例。使用 ref 的第二种方法更改调用者引用的对象。因此,“猫”!

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

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

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

由于您要传递引用类型(类),因此无需使用ref因为默认情况下仅传递对实际对象的引用 ,因此您始终在引用后面更改对象。

例:

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

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

只要您传入一个类,就可以在方法中更改对象而不必使用ref

refout行为类似,除了以下区别。

  • ref变量必须在使用前初始化。 out变量无需分配即可使用
  • out参数必须由使用该参数的函数视为未分配的值。因此,我们可以在调用代码中使用已初始化的out参数,但是函数执行时该值将丢失。

对于那些通过榜样学习的人(例如我),这就是安东尼 · 科列索夫(Anthony Kolesov)所说的

我创建了一些 ref,out 的最小示例,并通过其他示例来说明这一点。我没有介绍最佳实践,仅是了解差异的示例。

https://gist.github.com/2upmedia/6d98a57b68d849ee7091