我正在创建一个函数,我需要传递一个对象,以便它可以被函数修改。有什么区别:
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)
我应该用哪个,为什么?
当前回答
: 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();
}
}
}
其他回答
注意,在函数内部传递的引用参数是直接处理的。
例如,
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上工作。
它们几乎是一样的——唯一的区别是,作为out形参传递的变量不需要初始化,使用ref形参的方法必须将其设置为某个值。
int x; Foo(out x); // OK
int y; Foo(ref y); // Error
Ref形参用于可能被修改的数据,out形参用于已经使用返回值的函数(例如int.TryParse)的额外输出数据。
From the standpoint of a method which receives a parameter, the difference between ref and out is that C# requires that methods must write to every out parameter before returning, and must not do anything with such a parameter, other than passing it as an out parameter or writing to it, until it has been either passed as an out parameter to another method or written directly. Note that some other languages do not impose such requirements; a virtual or interface method which is declared in C# with an out parameter may be overridden in another language which does not impose any special restrictions on such parameters.
从调用者的角度来看,c#在很多情况下假设调用带有out形参的方法时,会导致传入的变量在未被读取之前就被写入。当调用用其他语言编写的方法时,这个假设可能不正确。例如:
struct MyStruct
{
...
myStruct(IDictionary<int, MyStruct> d)
{
d.TryGetValue(23, out this);
}
}
如果myDictionary标识了一个用c#以外的语言编写的dictionary <TKey,TValue>实现,即使MyStruct s = new MyStruct(myDictionary);看起来像一个任务,它可能会留下未修改的s。
注意用VB编写的构造函数。NET与c#中的方法不同,它不假设被调用的方法是否会修改任何out参数,并且无条件地清除所有字段。上面提到的奇怪行为不会发生在完全用VB或完全用c#编写的代码中,但是当用c#编写的代码调用用VB.NET编写的方法时就会发生。
public static void Main(string[] args)
{
//int a=10;
//change(ref a);
//Console.WriteLine(a);
// Console.Read();
int b;
change2(out b);
Console.WriteLine(b);
Console.Read();
}
// static void change(ref int a)
//{
// a = 20;
//}
static void change2(out int b)
{
b = 20;
}
你可以检查这段代码,它会向你描述它的完全不同 当你使用“ref”时,这意味着你已经初始化了int/string
但 当你使用out的时候 无论你是否初始化int/string,它都适用于这两种情况 但是u必须在函数中初始化int/string
裁判上场又出局。
您应该优先使用out,只要它能满足您的需求。