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

public void myFunction(ref MyClass someClass)

and

public void myFunction(out MyClass someClass)

我应该用哪个,为什么?


当前回答

如果你想将参数作为引用传递,那么你应该在将参数传递给函数之前初始化它,否则编译器本身会显示错误。但是对于out形参,您不需要在将对象形参传递给方法之前初始化它。可以在调用方法本身中初始化对象。

其他回答

out:

在c#中,一个方法只能返回一个值。如果希望返回多个值,可以使用out关键字。out修饰符返回为return-by-reference。最简单的答案是使用关键字“out”从方法中获取值。

您不需要在调用函数中初始化该值。 必须在被调用的函数中赋值,否则编译器将报错。

ref:

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

在调用函数之前,需要初始化变量。 为方法中的ref参数赋值不是强制的。如果不更改值,为什么需要将其标记为“ref”?

我要试着解释一下:

我想我们理解了值类型是如何工作的,对吧?值类型是(int, long, struct等)。当你将它们发送到一个没有ref命令的函数时,它会复制数据。在函数中对该数据所做的任何操作都只会影响副本,而不会影响原始数据。ref命令发送的是实际数据,任何变化都会影响函数外部的数据。

好了,让人困惑的部分,引用类型:

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

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

当你新建someobject时,会创建两部分:

存储某对象数据的内存块。 指向该块的引用(指针) 的数据。

现在,当你发送someobject到一个没有引用的方法时,它复制的是引用指针,而不是数据。现在你得到了这个:

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

两个引用指向同一个对象。如果你使用reference2修改某个对象的属性,它将影响由reference1指向的相同数据。

 (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 by ref发送给方法时会发生什么? 对某个对象的实际引用被发送给方法。所以你现在只有一个数据引用:

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

但这意味着什么呢?它的作用与不通过ref发送someobject完全相同,除了两件主要的事情:

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

由于您传递的是引用类型(类),因此不需要使用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。

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

所以当ref是双向的,out是唯一的。

假设多姆因为TPS报告的备忘录出现在彼得的隔间里。

如果Dom是一个参考参数,他就会有一份备忘录的打印副本。

如果多姆是一个多余的论据,他会让彼得打印一份新的备忘录,让他随身携带。