【C#基础】值类型和引用类型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26545305/article/details/52903658

一、前言:

    在备战软考的过程中,涉及到了原型模式,其中讲到了在浅复制的过程中,值类型和引用类型是有区别的。那么究竟什么是值类型,什么是引用类型呢?

在理解这两个概念之前,我们先谈一谈栈和堆。

    计算机的内存从概念上分,会有许许多多独立的块,堆和栈就是其中的两种内存块。是一种先进后出的数据结构,当我们调用一个方法时,假如这方法有参数的话,那么我们就需要在中为这个方法的参数方法所用到的变量局部变量)分配一小部分内存。当方法结束的时候,所占用的内存就会自动释放回栈中。堆是用于为类型实例(对象)分配空间的内存区域,当我们使用new创建一个对象的时候,new出来的东西放在中。更多详情,猛戳这里


二、值类型和引用类型:

    C#的类型一共分为两类,一种是值类型(Value Type),一类是引用类型(Reference)。

                 

    每一种编程语言的值类型都有一些非常细小的不同,C#的内置值类型共有七种:int、long、float、char、bool、enum、struct。而string类型是一种具有值类型特性的特殊引用类型,且按下不表。

           

三、函数调用时参数的传递方式:

    1、传值调用是将实参传递给被调用函数的形参。因此实参既可以是表达式,也可以是变量(或数组元素)。

    2、传地址调用是将实参地址传给被调用函数的形参。所以,实参必须有地址。因此实参必须是变量(数组),不能表达式常量(因为他们不存在地址)。

    3、如果采用传值方式调用,则形参值的变化不会影响实参。

    4、如果采用引用方式调用,则形参值的变化直接反映到实参。


四、举例:

    基于值类型的变量直接包含值。将一个值类型变量赋给另一个值类型变量时,将复制包含的值。举个例子:int  a =10; int b = a,此时b的值为10,当把a付给b时,开辟一块新的空间来保存b的值,b的值为10。当把a的值该为50时,会在a的空间保存50.。与b无关,此时b仍为10。                                                                              

而引用类型则与之不同,因为引用类型指向的是同一个地址。  


原型模式例子:

简历类:

<span style="font-family:KaiTi_GB2312;font-size:24px;">class Resume:ICloneable
{
     private string name;
     private string sex;
     private string age;
     private string timeArea;
     private string company;

   public Resume(string name)
   {
      this.name = name;
   }

//设置个人信息:

public void SetPersonalInfo(string sex,string age) 
  {
      this.sex = sex;
      this.age = age;
   }
//设置工作经历

public void SetWorkExperience(string sex,string age)
 {
       this.timeArea = timeArea;
       this.company = company;
  }

//显示

public void Display()
 {
     Console.WriteLine("{0} {1} {2}",name, sex, age);
     Console.WriteLine("工作经历:{0} {1}",timeArea, company);
  }

  public Object Clone()
   {
       return (Object)this.MemberwiseClone();
    }

}</span>
客户端调用代码:

<span style="font-family:KaiTi_GB2312;font-size:24px;">static void Main(string[] args)
{
   Resume a = new Resume("大鸟");
   a.SetPersonalInfo("男","29");
   a.SetWorkExperience("1998-2000","XX公司")

   Resume b = (Resume)a.Clone();
   b.setWorkExperience("1998-2006","YY企业")

   Resume c = (Resume)a.Clone();
   c.SetPersonalInfo("男","24");

   a.Display();     
   b.Display();
   c.Display();
 
   Console.Read();
}</span>


结果显示:
大鸟 男 29
工作经历  1998-2000  XX公司

大鸟 男 29
工作经历  1998-2006  YY公司

大鸟 男 24
工作经历  1998-2000  XX公司


工作经历类

<span style="font-family:KaiTi_GB2312;font-size:24px;"><span style="color:#ff6666;"><span style="color:#ff0000;">Class WorkExperience
{
    private string workDate;
    public string WorkDate
    {
	get {return workDate;}
        set {workDate = value;}
     }
    private string company;
    public string Company
    {
        get {return company;}
        set {company = value;}
     }
}</span></span></span>


简历类:

<span style="font-family:KaiTi_GB2312;font-size:24px;">class Resume:ICloneable
{
     private string name;
     private string sex;
     private string age;
   
   <span style="color:#ff6666;"><span style="color:#ff0000;">private WorkExperience work;</span> </span>//引用"工作经历"对象
   public Resume(string name)
   {
      this.name = name;
    <span style="color:#ffff00;">  </span><span style="color:#ff0000;"><span style="color:#ff0000;">work = new WorkExperience(); </span></span>   //在“简历”类实例化时同时实例化“工作经历”
   }

//设置个人信息:

public void SetPersonalInfo(string sex,string age) 
  {
      this.sex = sex;
      this.age = age;
   }
//设置工作经历

public void SetWorkExperience(<span style="color:#ff6666;">string workDate,string company</span>)
  {
      <span style="color:#ff6666;"> <span style="color:#ff0000;">work.WorkDate = workDate;
       work.Company = company</span>;</span>
  }

//显示

public void Display()
 {
     Console.WriteLine("{0} {1} {2}",name, sex, age);
     Console.WriteLine("工作经历:{0} {1}",<span style="color:#ff6666;"><span style="color:#ff0000;">work.WorkDate, work.Company</span></span>);
  }

  public Object Clone()
   {
       return (Object)this.MemberwiseClone();
    }

}
</span>


客户端调用:

<span style="font-family:KaiTi_GB2312;font-size:24px;">static void Main(string[] args)
{
   Resume a = new Resume("大鸟");
   a.SetPersonalInfo("男","29");
   a.SetWorkExperience("1998-2000","XX公司")

   Resume b = (Resume)a.Clone();
   b.setWorkExperience("1998-2006","YY企业")

   Resume c = (Resume)a.Clone();
   c.SetPersonalInfo("男","24");
   c.SetWorkExperience("1998-2003","ZZ企业");

   a.Display();     
   b.Display();
   c.Display();
 
   Console.Read();
}</span>


结果显示:

大鸟 男 29
工作经历  1998-2003  ZZ公司

大鸟 男 29
工作经历  1998-2003  ZZ公司

大鸟 男 24
工作经历  1998-2003  ZZ公司


分析:

    因为“简历”对象里的数据都是string型的,而string是一种拥有值类型特点的特殊引用类型,(在这里例子中可以看成是值类型。)前者是值类型,后者是类类型(属于引用类型)。所以两次的结果是不一致的。

    当执行c.SetWorkExperience("1998-2003","ZZ企业")之后,内存区域的数据变成 1998-2003  ZZ公司。因为引用类型的a、b、c指向的是这一块内存区域。所以a、b、c三个的显示结果都为:工作经历  1998-2003  ZZ公司

 

               



阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页