理解C#中参数
岁末了 正好有机会说说C#中的ref,Out与参数传递的关系。
第一次写技术博客,写的不好,多提意见。
---------------------------------------------------------------------分割线--------------------------------------------------
分割线上面是2014年提的笔,现在是2016年收的尾!
没有准备我就随便写了!
C#中数据类型分值类型和引用类型,值类型变量保存的变量的值、引用类型保存的是变量的地址。
C#中函数的参数都是按值类型传递的,除非使用了ref 或者out。
先证明函数的参数是按值类型传递的:
看下面的例子
public void f1(int a)
{
a=123;
}
int b=111;
f1(b);
console.write(b);//111
上面调用函数f1时候过程是实参b给形参a赋值,a和b是两个互不影响的变量。这个比较容易理解。下面再看引用类型的案例
public void f2(List<int> ll)
{
ll.add(2);
}
List<int> l=new List<int>();
l.add(1);
f2(l);
console.write(l.count);//2
如果参数是按值类型传递的那为什么会输出2呢?因为引用类型变量名称保存的是值的值。
List<int> l=new List<int>();//这句话实际上在内存中开辟了2块存储空间,一个是l,另一块是l的值指向的地址
当调用f2的时候实参l给形参ll赋值,按值类型赋值,l的值赋给ll,此时ll的值也是上面new出来的地址,此时实参l和形参ll都是指向的同一个内存空间,所以在f2中对ll操作的结果会影响到l。下面讲string类型的
public void f3(string s)
{
s="def";
}
string str="abc";
f3(str)
console.write(str)//abc
咦!为什么是abc?如果按照刚刚讲的应该输出def才对啊!原因是这样的 在C#中string类型是不可变的(为什么说string类型是不可变的类型?我理解的是string s="abc";实际上也是string s=new string(new char[]{'a','b','c'});含义是在内存总开辟了一块空间保存abc,然后把这块空间的地址赋给变量s。)
这里的str 给s赋值,也是按照值类型进行赋值,赋值之后str和s同时指向abc,关键在于在函数f3中s="def";这一句话也就是s=new string(new char[]{'d','e','f'});解释在内存中开辟了一段空间存储def 然后把这段空间的地址赋给s。此时str 和s已经发生了质变,str还是原来的str,s已经不是原来的s了!
下面代码可以查看变量的地址
static void Main(string[] args)
{
unsafe
{
string str = "abc";
fixed (char* p = str)
{
Console.WriteLine("字符串地址= 0x{0:x}", (int)p);
}
f3(str);
fixed (char* p = str)
{
Console.WriteLine("字符串地址= 0x{0:x}", (int)p);
}
}
string ss = new string("asdf");
Console.ReadKey();
}
public static void f3(string s)
{
unsafe
{
fixed (char* p = s)
{
Console.WriteLine("参数赋值前字符串地址= 0x{0:x}", (int)p);
}
s = "def";
fixed (char* p = s)
{
Console.WriteLine("参数赋值后字符串地址= 0x{0:x}", (int)p);
}
}
}
再来说说ref和out
其实他们很简单理解ref 和out都是强制把参数以引用类型传递!具体可以自己写个例子自测。最后附图一张