彻底澄清:C#方法参数
写这篇博客,主要是因为野文的这篇博客:关于C#函数对象参数传递的问题。
记得刚学C#时也曾被类似的这种问题搞得发疯:
值传递、引用传递、值类型参数、引用参数类型……
所以希望通过本文给初学者一点帮助。
首先,是一些基础知识。
1. C#的变量分为两种,一种是值类型(如int),一种是引用类型(如我们自定义的所有的class)。简单的说,值类型自身就存放有值,如int i = 10,你可以理解成i就是实实在在的10;而引用类型,MyClass obj = new Class(),obj本身并不存放new Class(),他只是关联到(指向)new Class()(篇幅所限,实在不能详细描述,但网上这方面的资料很多)。这里要特别提醒的是:切记,这是指变量本身的类型,变量本身的特征,本身的类型结构。
2. C#中的方法,会接受参数,对接受到的参数,C#也会有两种处理方法。一种是“值传递”(我们通常使用的就是这种),另一种是“引用传递” ,其特征就是关键字ref,如void MyMethod(ref int para)。所谓值传递,就是给方法传递一个变量的“副本”,所以变量本身不会受到方法的影响;而引用传递,就是将变量本身传递给函数(不够严谨,但可以这样理解),所以,变量会受到函数的影响。这里要特别提醒的是:切记,这是指变量被传递的方式,而不是变量本身的特征,本身的类型结构。
所以这里就有2*2=4种组合:
- 值类型的值传递 将值类型(如int i)的副本传递给方法
- 值类型的引用传递 将值类型(如int i)本身传递给方法
- 引用类型的值传递 将引用(如MyClass obj)的副本(注意:不是引用指向的内容new MyClass())传递给方法
- 引用类型的引用传递 将引用本身(如MyClass obj)传递给方法
最后,通过代码来说明问题吧!
{
static void Main(string[] args)
{
//i是值类型
int i = 10;
//objC1是引用类型
C objC1 = new C();
objC1.i = 100;
//objC1和objC2完全相等
C objC2 = objC1;
#region 以下测试代码请依次使用
////传一个值类型,传递的是i的副本,不会影响i本身
//ValuePass(i);
////将值类型按引用方式传递,就会将i本身传入方法,使i的值发生变化
//RefPass(ref i);
////objC是一个引用,将这个引用的副本传入方法,objC引用本身并不会变化
////但是,objC引用所对应的值在方法体内发生了改变
//ValuePassClass(objC1);
//objC1这个引用本身发生了改变(被new了,呵呵),所以新的objC1.i没有被赋值
RefPassClass(ref objC1);
#endregion
Console.WriteLine("i="+i);
Console.WriteLine("objC1.i=" + objC1.i);
Console.WriteLine("objC1 = objC2 is {0} ", ReferenceEquals(objC1, objC2));
Console.Read();
}
static void ValuePass(int m)
{
m += 10;
}
static void RefPass(ref int m)
{
m += 10;
}
static void ValuePassClass(C objC)
{
objC.i += 100;
//让objC发生改变
objC = new C();
}
static void RefPassClass(ref C objC)
{
objC.i += 100;
//让objC发生改变
objC = new C();
}
}
class C
{
public int i;
}
补充:
没想到这篇文章这么多回复。(回复是很有价值的,尤其是其中一些错误的理解)
这篇文章不是深入的、系统的讲解,是给一些“有一点认识,但还有些模糊”(如至少理解值类型和引用类型)的同学理清一个思路。
不能理解的同学最好读代码,运行一遍吧。
我感觉我的语言实在不够用了。