理解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都是强制把参数以引用类型传递!具体可以自己写个例子自测。最后附图一张

原文地址:https://www.cnblogs.com/chouxiaoya/p/4279112.html