您的位置:首页 > 编程语言 > C#

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

2016-10-23 18:58 375 查看
一、前言:

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

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

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

 

               
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: