理解参数传递
时间:2011-05-21 来源:scorpioying
说起来惭愧,直到今天,我才认真专研了参数传递究竟是怎么回事,按值传递和按引用传递到底有什么区别,想想以前好读书不求甚解,什么事就那么一带而过,考试得了高分拿了奖学金就觉得万事大吉了,无形之中荒废了多少青春岁月啊,好在对于学习知识来说任何时候都不算晚,这几天我一直有一种翻然醒悟的感觉,好像生命重获新生了,呃。。。夸张了一点哈,不过我很是开心,我喜欢这种状态。
这几天一直在读《你必须知道的.NET》,收获真的不少,在这里记录一下我的阅读日记,也算是对学过的内容进行一下复习了。
参数的传递,分为以下4种方式:
值类型的按值传递
引用类型的按值传递
值类型的按引用传递
引用类型的按引用传递
刚读到这四种方式时,觉得有点绕,没关系,静下心来,结合例子深入推敲一下,就很容易理解了。
1.值类型参数的按值传递
先看例子
class Program
{
static void Main(string[] args)
{
int number2 = 5;
Function(number2);
Console.WriteLine(number2);
}
private static void Function(int number1)
{
number1 += 1;
Console.WriteLine(number1);
}
}
输出结果为:
从输出结果来看,值类型的参数传递之后,并没有对原来的实例number2 产生影响,这是因为,从本质上来说,值类型内存分配于线程的堆栈上,它本身保存的就是实例本身,在传递时实际上传递的是实例的copy,也就是说在main函数中调用的Function方法中操作的是属于其本身的实例copy,也就是number1,因此首先输出了6,而这一操作并不会对原来的number2产生影响,因此执行最后一句时,输出的还是5,并不是6。
2.引用类型参数的按值传递
public class ValueType
{
public int number1 = 10;
}
class Program
{
static void Main(string[] args)
{
ValueType myValueType = new ValueType();
Function(myValueType); //引用类型的参数在传递时,传递的是引用地址的copy
Console.WriteLine(myValueType.number1);
}
private static void Function(ValueType i)
{
i.number1 = 11;
Console.WriteLine(i.number1);
}
从输出结果来看,参数传递后影响了原来的myValueType.number1,这是因为引用类型的参数按值传递传递的是参数的引用地址的copy,这里的按值传递的“值”指的就不是具体的数据了,所以会改变原来实例的地址指向,使得myValueType.number1指向了托管堆中的11,而不再是10了。
3.值类型的参数按引用传递
4.引用类型的参数按引用传递
从字面上来看,按引用传递,传递的一定是参数的地址,势必会改变原来对象的地址指向。
首先看值类型的按引用传递
class Program
{
static void Main(string[] args)
{
int number1 = 24;
TransferByValue(ref number1);
Console.WriteLine(number1);
}
//ref:值类型按引用传递 必须初始化
private static void TransferByValue(ref int oneValue)
{
oneValue = 23;
Console.WriteLine(oneValue);
}
}
输出结果:
从输出结果来看,按引用传递改变了原来对象的地址指向,number1的地址指向了23,也就是说,传递的是参数的地址,并不是参数的本身。
再来看引用类型参数的按引用传递
public class oneStr
{
public string str1 = "first";
}
class Program
{
static void Main(string[] args)
{
oneStr mystr = new oneStr();
Function(ref mystr.str1);
Console.WriteLine(mystr.str1);
}
private static void Function(ref string str)
{
str = "second";
Console.WriteLine(str);
}
}
输出结果:
从输出结果来看,引用类型参数的按引用传递改变了mystr.str1的地址指向,因此输出了second,而不是first
下面再来看看string的特殊,凡事总有特殊,特殊的就麻烦,不过总是千篇一律也没意思,呵呵。
先看个例子吧,string类型的参数传递
class Program
{
static void Main(string[] args)
{
string str2 = "second";
Function(str2);
Console.WriteLine(str2);
}
private static void Function(string str1)
{
str1 = "first";
Console.WriteLine(str1);
}
}
输出结果:
从输出结果上看,Function并没有对原来的str2产生影响,最后一条指令执行了之后输出的还是second。
main函数在执行过程中,调用Function方法时,具体过程为,先生成一个string对象str1,其值为“first”,把一个地址赋给str1,因此改变的是str1,而对于方法外的str2没有影响,所以str2的地址没有改变,因此指向的还是second。
所以说,要改变传递之后的结果,要用ref和out来修饰。
说了这么多,事实上我觉得自己理解的还不是那么透彻,以后再结合具体实例多加磨练吧,积累多了可能理解的就更好了。