C# OOP之五 深入理解值类型和引用类型

内存分配

我们在前面的章节已经了解了值类型和引用类型,下面我们重点讲下值类型和引用类型在内存中的分配情况。

值类型实例通常分配在栈(Stack)上,并且不包含任何指向实例数据的地址,因为变量包含了其实例数据。值类型主要包括简单类型、结构体类型和枚举类型。

例如如下代码:int  iCount=50;  //声明和初始化变量iCount

int iSum=iCount; //将iCount中的数据赋值给iSum

iCount++;            //增加iCount对iSum无关

在内存中给值类型分配的图形标识:


iCount

iCount=50


iSum

iSum=50

引用类型实例通常分配在堆(Heap)上,变量保存了实例数据的地址引用,主要包括以下类型:class、interface、delegate、object、string以及其他的自定义引用类型。

如下代码:

Class Car

{

Public string Model;

Public int  Money;

}

Static void Main()

{

Car       Ford=new Car();

Car       BYD=new Car();

}

注意:Ford、BYD中分别存放各自new Car()的内存地址,即通常说的引用。

结构

为什么要使用结构,针对小型相关变量组,例如,矩形的坐标或系统颜色的定义及操作,因为值类型直接分配内存效率比引用类型要高,所以结构还是有自己的用武之地。通常结构用来充当不同系统之间的数据传递的载体或者用在要求效率极高的软件中,比如游戏设计中就会采用大量的结构。

结构是从C语言遗留下来的一种类型,在C#中结构使用struct关键字定义。可以包含构造方法、常量、字段、方法、属性、索引器等成员。

结构类型语法:

访问修饰符  struct   结构名

{

     定义结构成员

    定义结构方法

    ….

}

针对每家的消费开销做的一个小案例如下:

using System;

class Program

{

public struct Spending

{

public string Spending_No;//开销号

public string Spending_Name;//开销名

public string Spending_Date;//开销日期

public double Spending_Cost;//开销金额

public string Spending_Memo;//开销备注

};

static void Main(string[]args)

{

//注意:区分结构型的变量可以直接赋值使用

//类变量必须将类的地址赋给对象

Spending mySp;

Console.WriteLine("请输入你的开销号:");

mySp.Spending_No=Console.ReadLine();

Console.WriteLine("请输入你的开销名:");

mySp.Spending_Name=Console.ReadLine();

Console.WriteLine("请输入你的开销日期:");

mySp.Spending_Date=Console.ReadLine();

Console.WriteLine("请输入你的开销金额:");

mySp.Spending_Cost=Convert.ToDouble(Console.ReadLine());

Console.WriteLine("请输入你的备注:");

mySp.Spending_Memo=Console.ReadLine();

Console.WriteLine("***********************************");

Console.WriteLine("您的开销编号:{0}",mySp.Spending_No);

Console.WriteLine("您的开销名:{0}",mySp.Spending_Name);

Console.WriteLine("您的开销日期:{0}",mySp.Spending_Date);

Console.WriteLine("您的开销费用:{0}",mySp.Spending_Cost);

Console.WriteLine("您的开销备注:{0}",mySp.Spending_Memo);

}

}

【struct同class的区别:

1.不支持继承

2.为值类型;class引用类型;

3.没有缺省的构造器;

4.使用:通常用来封装小型相关变量组,例如,矩形的坐标或库存商品的特征;类封装比较多的相关变量;

5.思考:同样的变量数的结构和类,谁的存取效率更高;为啥是结构!!!

6.结构不能声明默认构造函数(没有参数的构造函数)或析构函数

7.在结构中给实例字段赋值是错误的;

8.结构可以声明构造函数,但它们必须带参数。到第6章再讲,注意提醒我!!!

9.一个结构不能从另一个结构或类继承,而且不能作为一个类的基。所有结构都直接继承自 System.ValueType,后者继承自 System.Object。到继承再讲;

10.结构可以实现接口。注意到接口再讲;

枚举:

枚举用在什么地方?打开每个文件的属性,我们会看到“只读、隐藏、存档”;操作一个文件时,你可以采用只读、可写、追加等模式;设置系统级别时,你可能会选择紧急、普通和不紧急来定义。这些各式各样的信息中,一个共同的特点是信息的状态分类相对稳定,在.Net中可以选择以类的静态字段来表达这种简单的分类结构,但是更明智的选择显然是:枚举。

枚举定义:

访问修饰符 enum 枚举名 {值1,值2… }

n        枚举是一组描述性的名称

n        枚举定义一组有限的值,不能包含方法

n        对可能的值进行约束

n        枚举允许描述性名称表示整数值

案例:

….

枚举的典型应用(WinForm):

DialogResult choice;

choice = MessageBox.Show("确定要退出吗?", "退出系统",

MessageBoxButtons.OKCancel, MessageBoxIcon.Information);

if(choice == DialogResult.OK) //DialogResult是个枚举,指示对话框的返回值

Application.Exit();

做一个枚举扑克牌的花色,enum Suit{Clubs,Diamonds,Hearts,Spades};

在此处Suit枚举的基础类型默认为int型,枚举的指定类型只能是除char外的8种整数类型:byte、sbyte、ushort、int、uint、long和ulong,声明为其他类型将导致编译错误。

第一个元素默认为0,然后各成员依次加1;如果有成员显式设置相应值(比如8),则后续成员仍然在此值基础上加1;

数组和集合

一中小企业,老板给员工分配了一项任务,计算公司(25人)的平均销售额。

定义25个销售变量合适不?然后销售总额除以25可以吗?

为什么需要数组,我们去旅馆(宾馆)住宿,有不同的房间类型(单人间、双人间、三人间、豪华套房等),不同的房间类型又分不同的房号(比如从301—318;401—409等),这样客户根据不同的经济条件就可以选择相应的房间类型,然后旅馆为其分配相应的房间号。

数组:数组是一个变量,存储相同数据类型的一组数据

如何使用数组四步骤:

 

1、声明数组

   int[ ] a;

2、分配空间

a = new int[5];

3、赋值

a [0] = 8;

4、处理数据

a [0] = a[0] * 10;

1、声明数组: 告诉计算机数据类型是什么

语法:

数据类型    数组名[ ] ;

数据类型[ ]    数组名;

int[ ] Sales;             //销售业绩

int Sales[ ];             //销售业绩

String[ ] empName;        //员工姓名

2、分配空间: 告诉计算机分配几个格子

   语法:

      声明数组并分配空间

数据类型[ ]  数组名   =  new   数据类型[大小]  ;       

Sales = newint[30];   //数组为引用类型,所以,需要new

Sales = newint[6];

empName = newString[30];

3、赋值:向分配的格子里放数据

   score[0] = 89;

score[1] = 79;

score[2] = 76;

……

思考:考虑如何一次多个赋值,希望大家给出解决方法

4、对数据进行处理:计算25位员工的平均销售额

for(int i = 0; i< 25; i ++){

Sales[i] = Console.ReadLine();

}

int sum = 0;

double avg;

for(int index = 0;index < Sales.length; index++){

sum = sum + Sales [index];

}

avg = sum /Sales.length;

回顾问题:一中小企业,老板给员工分配了一项任务,计算公司(25人)的平均销售额,使用动态录入并赋值的方式计算平均销售额

Foreach循环

Foreach(基本数据类型  变量名/对象名  in <array>)

{

循环遍历数组中的各元素

}

定义二维数组:

数据类型[,]数组名=new 数据类型[行数,列数]

针对多维数组一般都采用使用循环来初始化数据

案例:求1个3行3列距阵对角线的和,数字距阵如下:

1     2     3

4     5     6

7     8     9

ClassTwoArray

{

static void Main(string[]args)

{

int[,]a={{1,2,3},{4,5,6},{7,8,9}}

int sum=0;

for(int i=0;i<3;i++)

{

if(i==j||i+j==2)

sum+=a[i,j];

}

}

Console.WriteLine(“和为:{0}”,sum);

}

思考:注意体会循环中判断

接下来,我们来看一下,Main()中的参数string[]args,我们已经学过方法参数和数组了,那么Main()中的东东是什么呢?就是一个string类型的数组而已。

那么这个数组有啥用呢?

我们称之为Main()的命令行参数,使用方法是在运行时,输入数据,传递给args数组,代码如下:

class CommandLine

{

staticvoid Main(string[] args)

{

System.Console.WriteLine("参数总数{0}", args.Length);

for (int i = 0; i< args.Length; i++)

{

System.Console.WriteLine("args[{0}]= [{1}]", i, args[i]);

}

}

}

编译:csc CommadLine.cs

运行如下几种命令行参数,试验效果如何?


命令行输入


传递给 Main 的字符串数组


CommadLine.exe 老板 Boss CEO


"老板"

"Boss"

"CEO"


CommadLine.exe老板 Boss


"老板"

" Boss"


CommadLine.exe "老板 Boss " CEO


"老板 Boss "

"CEO"

实践问题:

1.如果数组声明为 int[] arr = new int[16],则数组中的元素个数为______.

A.15  B.16    C.17    D.18

2.看一些代码,输出的结果为( )

using System;

class nameee

{

public static void Main()

{

int Number1=0;

int Number2=0;

int[] Array1=new int[]{12,33,24,65,26,47,38,29,90,41,99,81};

foreach (int Ctr inArray1)

{

if (Ctr%2 == 1)

Number1++;

else

{

Number2++;

Console.WriteLine (Car);

}

}

}

}

A. 12,24,26,38,90   B.33,65,47,29,41,99,81

C.Ctr             D. 12, 24, 26,29,33,38, 41, 47, 65,81, 90, 99

3.如果数组声明为string [] arr = new string[5],则数组的基类型是______.

A.string   B.int    C.long    D.byte

4.在数组中,它的下标即数组的第一个位置是从______开始。

A.0      B.-1     C.1     D.2

小结:

在本章中,我们主要学习了:

u      值类型和引用类型的内存分配

u      值类型的两种新类型:结构与枚举的定义与使用

u      数组的使用

英语词汇:

英文            全文                                        中文

Struct                                                           结构

Datatype                                                               数据类型

Namespace                                             命名空间

Detail                                                      详细、详情

Product                                                      产品

Cost                                                        花费

Advance                                           高级

Enum                                                       枚举

Array                                                      数组

Source                                                    源

Target                                                     目标

Code                                                       代码

Check                                                     检查

Loop                                                       循环

Foreach                                                          循环

Param                                                                 参数

Total                                                       总共的

Content                                            内容

Row                                                        行

Length                                                     长度

Rank                                                       排; 横列; 行列

Sort                                                  排序

Clear                                                         清空

Index                                                              索引

Framework                                                       框架

Collection                                                集合

Queue                                                     队列

Stack                                                      堆栈

练习项目:

1.    利用结构来设计一个矩形,来实现求其面积,注意(设计矩形结构的Height、Widtd,可以适当参考MSDN)

课程项目扩充:

2.猜数游戏:从键盘中任意输入某员工销售额,判断销售数组中是否包含此销售额

3.求销售数组中的最大值。

时间: 2024-07-31 10:16:51

C# OOP之五 深入理解值类型和引用类型的相关文章

理解C#值类型和引用类型

网上偶尔浏览到这一篇文章,还不错就修改了下分享给大家. 工作许久了,可是对C#值类型和C#引用类型却一直无法很好的理解.这两天花了不少时间查找资料,看文章,终于有所收获,在此将自己理解整理出来,方便日 后自己查看,同时希望对跟我有一样困惑的朋友有所帮助.废话不多说,下面开始说说怎么理解值类型和引用类型! C#值类型数据直接在他自身分配到的内存中存储数据,而C#引用类型只是包含指向存储数据位置的指针. 1.值类型 那么有哪些类型是C#值类型的呢,我把他们归纳成三类: 1)基础数据类型(string

js值类型与引用类型

JavaScript值类型和引用类型有哪些 (1)值类型:数值.布尔值.null.undefined. (2)引用类型:对象.数组.函数. 三.如何理解值类型和引用类型及举例 我们可以用"连锁店"和"连锁店钥匙"来理解,不知道以下比喻合不合适,^-^. (1)值类型理解:变量的交换等于在一个新的地方按照连锁店的规范标准(统一店面理解为相同的变量内容)新开一个分店,这样新开的店与其它旧店互不相关.各自运营. [值类型例子] 代码如下: function chainSt

JavaScript基本数据类型及值类型和引用类型

在JavaScript中四种基本的数据类型:数值(整数和实数).字符串型(用“”号或‘'括起来的字符或数值).布尔型(使True或 False表示)和空值.在JavaScript的基本类型中的数据可以是常量,也可以变量.由于JavaScript采用弱类型的形式,因而一个数据的 变量或常量不必首先作声明,而是在使用或赋值时确定其数据的类型的.当然也可以先声明该数据的类型,它是通过在赋值时自动说明其数据类型的. javascript中的变量 javascript中的变量只是一个占位符,前言已经说过了

C#值类型和引用类型用C语言理解

我刚用C#一个来月,可能理解得不对,还请大家指教. 读懂文章你需要对C语言的指针有所理解. 需要注意区别:对C\C++来说,任何类型都可以当成C#的"引用类型",因为有指针. [在内存上] void foo() { int aaa = 0; //值类型,aaa在Stack上分配(SUB ESP,XX) int* paaa = new int[123]; //引用类型,paaa在Heap上分配,HeapAlloc(GetProcessHeap()...) foo2(&aaa);

值类型和引用类型深入理解

引言 山重水复疑无路,柳暗花明又一村,越探究越接近事物的本质.最近在学习原型模式(Prototype)时,发现原型模式本质就是对一个类原始数据的克隆,但在学习深拷贝和浅拷贝时又发现与值类型和引用类型有着千丝万缕的联系.回想好久都没有温习基础,于是就整理了值类型和引用类型的随笔,本文内容比较基础,对于想继续深入研究的同学可以查看IL更深入探究. 1.值类型(ValueType) 值类型包括:数值类型,结构体,bool型,用户定义的结构体,枚举,可空类型. 值类型的变量直接存储数据,分配在托管栈中.

c# 我所理解的 值类型 and 引用类型

一直以来对于值类型和引用类型都只是一个模糊的概念,趁最近有空深入理解了下. 先说说值类型,在msdn上是这样介绍值类型的. 意思就是值类型直接包含值. 变量引用的位置就是值所在内存中实际存储的位置,所以捏,假如你将一个原始变量的值赋给另一个变量,会在新变量的位置创建原始变量的值的一个内存副本.两个变量是不可能引用同一个内存位置滴(除非其中有参数是out 或者ref 参数).而更改原始变量的值不会影响另一个变量的值,因为变量各有各的存储位置.如下图所示(自己画的有点丑,别介意哈) 翻了下<c#本质

值类型,引用类型 结合 栈,堆的理解

值类型与引用类型的区别: 值类型最直接的的就是 int double bool 等字节已经固定的类型,继承自 ValueType 类 引用类型,可以说都继承自 object 类型. 值类型与引用类型在栈与堆中的存在形式: 值类型 :在堆中没有开辟空间,直接在栈中给予空间存值,在引用的时候直接复制值给新的变量 引用类型:在堆中开辟内存,栈中只是存着一个在堆中的地址值.在引用的时候是把对象的地址值给了新的变量. 有更好的解释欢迎指点

C#中关于值类型和引用类型的个人理解

值类型,除了最终继承自Object,还继承自ValueType 值类型继承ValueType,ValueType继承Object.(c#中所有的类型都最终继承自Object) 创建引用类型时,runtime会为其分配两个空间,一块空间分配在堆上,存储引用类型本身的数据,另一个块空间分配在栈上,存储对堆上数据的引用(实际上存储的堆上的内存地址,也就是指针). 创建值类型时, runtime会为其分配一个空间,这个空间分配在变量创建的地方,如: 如果值类型是在方法内部创建,则跟随方法入栈,分配到栈上

定义类+类实例化+属性+构造函数+匿名类型var+堆与栈+GC回收机制+值类型与引用类型

为了让编程更加清晰,把程序中的功能进行模块化划分,每个模块提供特定的功能,而且每个模块都是孤立的,这种模块化编程提供了非常大的多样性,大大增加了重用代码的机会. 面向对象编程也叫做OOP编程 简单来说面向对象编程就是结构化编程,对程序中的变量结构划分,让编程更清晰. 类的概念: 类实际上是创建对象的模板,每个对象都包含数据,并提供了处理和访问数据的方法. 类定义了类的每个对象(称为实例)可以包含什么数据和功能. 类中的数据和函数称为类的成员:数据成员        函数成员 数据成员: 数据成员