我正在创建一个函数,我需要传递一个对象,以便它可以被函数修改。有什么区别:
public void myFunction(ref MyClass someClass)
and
public void myFunction(out MyClass someClass)
我应该用哪个,为什么?
我正在创建一个函数,我需要传递一个对象,以便它可以被函数修改。有什么区别:
public void myFunction(ref MyClass someClass)
and
public void myFunction(out MyClass someClass)
我应该用哪个,为什么?
当前回答
简洁的回答。
ref和out关键字都用于引用传递。 关键字为ref的变量必须有一个值或必须引用一个对象 或者在它传递之前为null。 与ref不同,关键字为out的变量必须有一个值或必须 在对象传递后引用对象或null以及不需要 在传递之前有一个值或引用一个对象。
其他回答
裁判上场又出局。
您应该优先使用out,只要它能满足您的需求。
我要试着解释一下:
我想我们理解了值类型是如何工作的,对吧?值类型是(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表示Ref参数中的值已经设置,方法可以读取和修改它。 使用ref关键字等同于说调用方负责初始化形参的值。
Out告诉编译器,对象的初始化是由 函数需要赋值给out形参。 没有分配是不允许的。
https://www.codemaggot.com/ref-and-out-keywords/
对于那些以身作则的人(比如我),以下是安东尼·科索夫所说的。
我创建了一些ref、out和其他例子来说明这一点。我并没有介绍最佳实践,只是举例来理解它们之间的差异。
https://gist.github.com/2upmedia/6d98a57b68d849ee7091
扩展狗和猫的例子。带有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;
}