.net中值类型、引用类型理解的c#代码示例

下面是以前在公司的时候给别人讲解值类型、引用类型时创建的c#代码示例,从实际使用时的角度出发,对于初学者还是很有帮助的。这里并没有深入讲解值类型包含引用类型成员时(如struct)在内存中的存放情况等等,出于简洁,并没有给出。这些内容很简单,如需了解,可以查阅其他资料。

所有需要讲解与注意的地方都以注释的方式放到的代码里面。

namespace ValueAndReferenceTransfer
{
    class Program
    {
        static void Main(string[] args)
        {
            int a = 1;
            Modify(a);
            //传的是a的一个拷贝
            Console.WriteLine(a);//1

            Modify(ref a);
            //传的是一个指向栈(stack)上存储a的内存块的指针
            Console.WriteLine(a);//2

            Person person = new Person("Me");
            //person是一个存储在stack上的引用,这个引用指向堆(heap)中的一个内存块,这个内存块中是Person实例的内容
            Modify(person);
            //传的是person这个引用的一个拷贝,这两个指向heap中的同一块区域

            #region 这段的理解尤其重要
            Console.WriteLine(person.name);//A
            //因为其拷贝和它指向heap中的同一块内容,所以在被调函数中的对heap中内容的改动对这里的输出产生了影响,输出A而不是Me
            Modify1(person);//传的仍然是引用的一个拷贝
            Console.WriteLine(person.name);//A
            //因为改变的是拷贝引用本身,而不是其指向的堆中的内容,所以仍然输出A
            #endregion

            Modify(ref person);
            //传输的是指向栈上存储person引用的内存块的指针(可以理解为指针的指针了)
            Console.WriteLine(person.name);//C
            //因为person引用本身被改变,所以输出的应该是改变以后的内容
        }

        static void Modify(int i)
        {
            Console.WriteLine(++i);//2
            //改变的是a的拷贝
        }
        static void Modify(ref int i)
        {
            Console.WriteLine(i.GetType());
            Console.WriteLine(++i);//2
            //改变的是a本身
        }
        static void Modify(Person myPerson)
        {
            myPerson.name = "A";
            //改变的是这个拷贝引用指向的heap中的内存块的内容,其本身没有改变            
        }
        static void Modify1(Person myPerson)
        {
            myPerson = new Person("B");
            //改变的是这个拷贝引用本身,被重定向了(不再指向原先的内存块了),对原来指向的堆中的内容没有影响
            Console.WriteLine(myPerson.name);//B
        }
        static void Modify(ref Person myPerson)
        {
            myPerson = new Person("C");
            //通过指向引用的指针,改变的是引用本身,这个引用被重定向了,并且指向的heap中新分配的Person实例的name是C
            //多考虑一点,堆中原来的那个内存块已经没有引用再指向它了,所以它现在变成了一块垃圾,会在下次垃圾回收时进行回收
        }
    }

    public class Person
    {
        public string name;
        public Person(string name)
        {
            this.name = name;
        }
    }
}

 

 

 

转载于:https://www.cnblogs.com/CSharpSPF/p/3452689.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值