由堆栈所能想到的以及ref,out参数

由堆栈所能想到的??

提到堆栈区别,大部分首先想到的是,“值类型存储在栈中,引用类型存储在堆中,引用类型在栈上存储指向堆的地址”这句话。说这个我先想说一下值类型和引用类型,以及值传递和引用传递,关于值类型有哪些,以及引用类型有哪些,这些可以自己去了解。

将一个值类型赋值给另一个值类型,是将值得本身全部赋值过去,简言之,就是值类型的值传递传递的是值得本身,如下

    class Program
    {
        //值传递&引用传递

         static void Main(string[] args)
        {
            //值类型:int double char bool enum... 存储值的
            //引用类型:string 数组 自定义类,集合 object.. 存储对值的引用的(可以理解为存储值在堆中的数据地址)
            //这里有篇博客说的很好:http://www.cnblogs.com/jiajiayuan/archive/2011/09/23/2185966.html
            unsafe
            {
                //值传递
                int n1 = 10;//地址:0x058***98
                int n2 = 20;//地址:0x058***94
                n1 = n2;
                int* adress_n1 = &n1;//使用C#指针需要将语句块标记为unsafe表示不安全上下文
                int* adress_n2 = &n2;
                Console.WriteLine(n1);
                Console.WriteLine(n2);
                Console.WriteLine((int)adress_n1);//输出n1在栈上的地址
                Console.WriteLine((int)adress_n2);//输出n2在堆栈上面的地址
                Console.ReadKey();
            }
        }
    }

值传递编辑图示


flag:这里待会将会和ref关键字有联系。

下面可以看看引用类型的引用传递又是怎么一回事。

        //引用传递
        static void Main(string[] args)
        {
            Person p1 = new Person();
            p1.Name = "pc";
            Person p2 = new Person();
            p2.Name = "ppcc";
            p2 = p1;
            Console.WriteLine(p1.Name);
            Console.WriteLine(p2.Name);
            Console.ReadLine();
        }
    }

    public class Person
    {
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    }

引用传递编辑图示


我们知道字符串也是引用类型,但是对于字符串由于字符串拥有不可变性,所以很特殊。

        static void Main(string[] args)
        {
            string s1 = "pc";//字符串引用类型,但是字符串拥有不可变性
            string s2 = s1;
            s2 = "ppcc";
            Console.WriteLine(s1);
            Console.WriteLine(s2);
            Console.ReadLine();
            //输出结果
            //pc
            //ppcc
        }

ref参数

        static void Main(string[] args)
        {
            int a = 20;
            Test1(a);
            Console.WriteLine(a);//输出是多少?是20
            Console.ReadLine();
        }

        public static void Test1(int a1)
        {
            a1 += 1;
        }
在Test1里面a的值是21,但是这个方法由于没有返回值,所以,最后输出结果还是原值。那这个例子和ref参数就有关了,有资料说,ref参数可以将值类型的传递改成传递地址,通过对地址的操作改变值类型本身。

        static void Main(string[] args)
        {
            int a = 20;
            Test1(ref a);
            Console.WriteLine(a);//输出是多少?是21
            Console.ReadLine();
        }

        public static void Test1(ref int a1)
        {
            a1 += 1;
        }

关于它和out参数的区别,记住一句话,因为ref参数是从外部传递到函数里面的,所以要求必须在函数外部进行赋值,而out参数因为是从方法内部传递出去的,所以要求在方法内部必须对其进行有值操作。

out参数

        static void Main(string[] args)
        {
            int a = 20;
            int b;//使用out参数的时候 这里不用赋值,因为值是从一个函数里面传递出来的
            //Test1(ref a);
            Test2(out b);
            Console.WriteLine(b);//输出是多少?是-1
            Console.ReadLine();
        }

        //public static void Test1(ref int a1)
        //{
        //    a1 += 1;
        //}

        public static void Test2(out int b)
        {
            b = 3;//在函数内部必须赋值
            b -= 1;
        }

留下的思考就是,out参数是否也是通过改变参数的传递方式?链接一个为什么C#中属性不可以使用ref,out参数

http://book.51cto.com/art/200910/158498.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值