博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#笔记(一):类型,泛型,集合
阅读量:6956 次
发布时间:2019-06-27

本文共 3688 字,大约阅读时间需要 12 分钟。

最近在学习.NET Framework 高级编程这本书,感觉挺有意思的,于是根据自己的理解,做了笔记,总结下内容。本文笔记主要是从.NET类型,泛型,集合这三个方面进行描述。

本文内容:

  1. 类型

  2. 泛型

  3. 集合

 


 

1.类型

类型是对程序要处理的数据对象的分类。不同的数据对象占用存储空间不同,操作处理方法不同,所以必须分门别类;

(1)C#的主要类型有:

基本类型:数值、字符、逻辑型、字符串、对象(object)

系统或自定义的类型:结构、枚举、类等等。

上述这些类型,所占的内存空间不同。有的类型占用内存空间是确定的,有的不确定。

根据它们被分配存储空间方式的不同,可以分为:值类型/引用类型两大类。

上述的类型中,你是否又能区分它们属于哪一类呢?

基本数据类型大部分是值类型,除了object, string属于引用类型;类是引用类型;结构和枚举是值类型。

(2)内存的使用分别:栈(stack), 堆(heap) 静态区(static)。

 

值类型直接分配在栈上;

引用类型包括两部分:对象的引用(地址)在栈(stack)上,对象本身在堆(heap)上。

静态区(static)存放的是与对象的实例无关的部分。即当程序一装入内存,就要分配好。

如:入口方法,构造方法,常量,其他用static修饰的成员。

(3)举例:

例一:

int x, y=0; x = y; y = 9;

 

例二:设有类Myobj定义为:

class Myobj {
public int age; public string name; } Myobj a, b; a = new Myobj(); a.age = 28; a.name = "puppy"; b = a; a.age = 18; a.name = "doggy"; Console.WriteLine(b.age); Console.WriteLine(b.name);

 

例三:

string x, y="string1"; x = y; y = "string2"; Console.WriteLine(x);

 

第一个例子输出是0。当y=9时,实际上是在栈中重新分配一个内存地址。

第二个例子输出是18和doggy。b=a时,a和b同时指向一个地址空间

第三个例子输出是string1。string是一个特殊的引用类型。 string实例在内存中不可修改。当需要修改时,总是创建一个新的实例,并将变量指向新的实例。

(在程序中频繁修改字符串变量,会产生大量内存垃圾。这是我们要使用StringBuilder类的原因)

 

(4)装箱和拆箱

装箱:将值类型转换为引用类型,按照自己的理解来说在堆中生成一个新的对象,栈中原本的地址指向该对象。

拆箱:将引用类型转换为值类型,大致同上,过程相反。

int x=1; Object y=x;//装箱 int z=(int)y;/拆箱

 

2.泛型

问题的缘起:

请看一个Stack的程序。Stack是一种数据结构。可以存放许多元素,遵循后进先出的原则。

举例:(Stack)

class StackOfInt {
private int[] m_ItemArray; private int m_Index = 0; public const int Max_Size = 100; public StackOfInt () { m_ItemArray = new int[Max_Size]; } public int Pop() {
if (m_Index == 0) throw new System.InvalidOperationException("Can't Pop an empty stack."); return m_ItemArray[--m_Index]; } public void Push(int item){
if (m_Index == Max_Size) throw new System.InvalidOperationException("Can't push an item on a full stack."); m_ItemArray[m_Index++] = item; } }

 

缺点:这样的栈用object类型作为元素类型,可以供所有类型使用

但在压入元素时,要装箱;取用元素时要拆箱,代价很大,执行效率低;

类型不安全。转换类型时容易出错。

解决方案:如果我们可以在Stack类的定义中,提供一个类作参数,则可以简化此问题的解决。泛型的定义:在定义一个类型时,使用另一个或几个类型为参数,类型参数用<>围住,放在所定义的类型名后面。

在使用带有类型参数的泛型类型时,同时要给定参数类型的具体类型。

举例:定义泛型Stack类

class Stack
{
private T[] m_ItemArray; private int m_Index = 0; public const int Max_Size = 100; public Stack() { m_ItemArray = new T[Max_Size]; } public T Pop() {
if (m_Index == 0) throw new System.InvalidOperationException("Can't Pop an empty stack."); return m_ItemArray[--m_Index]; } public void Push(T item){
if (m_Index == Max_Size) throw new System.InvalidOperationException("Can't push an item on a full stack."); m_ItemArray[m_Index++] = item; } }

 

泛型的优点:

让代码更具有通用性,更简洁;

强类型,类型安全,不用担心类型转换错;

不用浪费很多装箱、拆箱的时间。

3.集合

集合类型是其对象中包含多个其他对象的特殊类型。

数组是最常用的集合类型。

要进一步理解的是,当我们在程序中申明一个数组时,实际上是指示CLR在执行期间帮我们创建和管理一个集合类型;

该集合类型的基类为System.Array

所以,我们可以对数组使用一些固有的属性和方法,如Length,Rank,Copy,Clone。他们来自Array类;还可以对数组用foreach来遍历。这是因为Array已经实现IEnumerable 接口。

由此我们可以牢记,数组是引用类型。可以用数组作为方法的参数,不使用ref也可以从方法中传出修改的结果

举例:

using System.Collection.Generic; public class Program {
public static void Main() {
List
list = new List
(3); for (int i=0; i<8; i++) {
list.Add(i); System.Console.WriteLine(“Count: {
0} Capacity: {
1}”, list.Count, list.Capacity); } list.TrimExcess(); System.Console.WriteLine(“Count: {
0} Capacity: {
1}”, list.Count, list.Capacity ); } }

 

作者:
出处:
欢迎转载或分享,但请务必声明文章出处。如果文章对您有帮助,希望你能
推荐
关注
 
 

转载于:https://www.cnblogs.com/ForEvErNoME/archive/2012/02/15/2353375.html

你可能感兴趣的文章
Oracle 白皮书-Oracle Data Guard 快速启动故障切换指南(1)
查看>>
通过案例学调优之--和 SHARED POOL 相关的主要 Latch
查看>>
sql server 数据库索引
查看>>
[spring-framework]Spring中集成RMI(远程方法调用)
查看>>
活动目录实战之十二 windows 2008 r2 AD 备份和还原 (下)-授权还原
查看>>
SQL2012群集
查看>>
I/O重定向
查看>>
VIM配置文件
查看>>
国外免费网管软件推荐
查看>>
2015年工作中遇到的问题:41-50
查看>>
python-字典
查看>>
收藏列表
查看>>
Linux信任主机(SSH)
查看>>
oracle数据库安装条件查询
查看>>
云服务IaaS,PaaS,SaaS的区别
查看>>
MFC 菜单
查看>>
ES权威指南[官方文档学习笔记]-6 document oriented
查看>>
ES权威指南[官方文档学习笔记]-23 Add an index
查看>>
Badboy自动化测试工具4 运行脚本
查看>>
IEC61850之TrgOps报告触发选项各bit位表示含义
查看>>