各位大侠,小弟有一事不明,特此请教。
C#中的变量有“值类型(例如,int)”和“引用类型(例如,类)”两种,而我认为ref参数只对值类型“有影响”,而对引用参数“没有任何影响”。我这么说可能比较模糊,下面举个例子。我自己定义了一个函数:
void test(ref int i)
{
i = 10;
}
然后在主程序中:
static void Main(string[] args)
{
int i = 100;
test(ref i);//调用自定义函数
Console.WriteLine("i=" + i.ToString());
}
程序结果显示i=10,证明引用参数(ref)将函数中对i的改变带回了主函数中,这是在我意料之中的,即我所说的“引用参数对值类型参数有影响”。
但是对于引用类型(比如“类”),就不同了!因为类本身就是引用类型,所以加ref与不加ref有什么区别呢?例如,我定义了一个类:
class testclass
{
public int i;
}
又定义了一个函数:
static void test(testclass a)//注意:这里我没用ref
{
a.i = 10;
}
然后在主程序中:
static void Main(string[] args)
{
testclass a = new testclass();
a.i = 100;
test(a);
Console.WriteLine("a.i=" + a.i.ToString());
Console.ReadLine();
}
程序输出:a.i=10。这个结果与“加上ref”之后完全相同,所以我认为ref对像“类”之类的引用类型参数没有影响。但是我最近学习c#网络编程中的UDP部分,其中有一个ReceiveFrom函数,它的一个简单重载如下:
ReceiveFrom(byte[] data, ref EndPoint Remote)
看到这里,我就疑惑了:为什么在这里的Remote参数要写成ref参数呢?EndPoint是一个类,所以本身就是一个引用类型,那么微软的牛人们为什么要在此参数前面加上一个ref呢??
百思不得其解,特此请教,望各位指点!
C#中的变量有“值类型(例如,int)”和“引用类型(例如,类)”两种,而我认为ref参数只对值类型“有影响”,而对引用参数“没有任何影响”。我这么说可能比较模糊,下面举个例子。我自己定义了一个函数:
void test(ref int i)
{
i = 10;
}
然后在主程序中:
static void Main(string[] args)
{
int i = 100;
test(ref i);//调用自定义函数
Console.WriteLine("i=" + i.ToString());
}
程序结果显示i=10,证明引用参数(ref)将函数中对i的改变带回了主函数中,这是在我意料之中的,即我所说的“引用参数对值类型参数有影响”。
但是对于引用类型(比如“类”),就不同了!因为类本身就是引用类型,所以加ref与不加ref有什么区别呢?例如,我定义了一个类:
class testclass
{
public int i;
}
又定义了一个函数:
static void test(testclass a)//注意:这里我没用ref
{
a.i = 10;
}
然后在主程序中:
static void Main(string[] args)
{
testclass a = new testclass();
a.i = 100;
test(a);
Console.WriteLine("a.i=" + a.i.ToString());
Console.ReadLine();
}
程序输出:a.i=10。这个结果与“加上ref”之后完全相同,所以我认为ref对像“类”之类的引用类型参数没有影响。但是我最近学习c#网络编程中的UDP部分,其中有一个ReceiveFrom函数,它的一个简单重载如下:
ReceiveFrom(byte[] data, ref EndPoint Remote)
看到这里,我就疑惑了:为什么在这里的Remote参数要写成ref参数呢?EndPoint是一个类,所以本身就是一个引用类型,那么微软的牛人们为什么要在此参数前面加上一个ref呢??
百思不得其解,特此请教,望各位指点!
private void test(object[] arrObj)
{
arrObj[0]="arrObj[0]可以改变";
arrObj=new object[]{"arrObj可以改变"};
}
//传入引用
private void test(ref object[] arrObj)
{
arrObj[0]="arrObj[0]可以改变";
arrObj=new object[]{"arrObj可以改变"};
}
private void button1_Click(object sender, System.EventArgs e)
{
object[] o=new Object[]{"jinjazz"};
test(o);
MessageBox.Show(o[0].ToString());test(ref o);
MessageBox.Show(o[0].ToString());
}
C#和C++不同,一个class obj是一个引用值,而struct obj是一个副本值。
形如:func(class1 obj)会将obj对象的引用传入func1函数,所以在func内部可以修改obj的实际值,而func(struct strObj)只是将strObj的一个副本传入,所以strObj本身不会被修改。
所以,对于struct 变量和系统内建数据类型如int,string等需要一个类似C++中传引用的机制来在函数内部修改传入参数实际值,ref就是这个功能。
方法参数上的 ref 方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。若要使用 ref 参数,必须将参数作为 ref 参数显式传递到方法。ref 参数的值被传递到 ref 参数。传递到 ref 参数的参数必须最先初始化。将此方法与 out 参数相比,后者的参数在传递到 out 参数之前不必显式初始化。属性不是变量,不能作为 ref 参数传递。如果两种方法的声明仅在它们对 ref 的使用方面不同,则将出现重载。但是,无法定义仅在 ref 和 out 方面不同的重载。例如,以下重载声明是有效的:class MyClass
{
public void MyMethod(int i) {i = 10;}
public void MyMethod(ref int i) {i = 10;}
}
但以下重载声明是无效的:class MyClass
{
public void MyMethod(out int i) {i = 10;}
public void MyMethod(ref int i) {i = 10;}
}
有关传递数组的信息,请参见使用 ref 和 out 传递数组。示例
// cs_ref.cs
using System;
public class MyClass
{
public static void TestRef(ref char i)
{
// The value of i will be changed in the calling method
i = 'b';
} public static void TestNoRef(char i)
{
// The value of i will be unchanged in the calling method
i = 'c';
} // This method passes a variable as a ref parameter; the value of the
// variable is changed after control passes back to this method.
// The same variable is passed as a value parameter; the value of the
// variable is unchanged after control is passed back to this method.
public static void Main()
{
char i = 'a'; // variable must be initialized
TestRef(ref i); // the arg must be passed as ref
Console.WriteLine(i);
TestNoRef(i);
Console.WriteLine(i);
}
}
输出
b
b