[.net 面向对象编程基础] (17) 数组与集合

[.net 面向对象编程基础] (17) 数组与集合

学习了前面的C#三大特性,及接口,抽象类这些相对抽象的东西以后,是不是有点很累的感觉。具体的东西总是容易理解,因此我们在介绍前面抽象概念的时候,总是举的是具体的实例以加深理解。

本节内容相当具体,学起来也相当轻松。

1.数组

1.1 什么是数组?

数组是一种数据结构,包含同一个类型的多个元素。

1.2数组的初始化

string[] mystringArray;

类型+方框号 数组名

1.3数组初始化

我们知道数组是引用类型,所以需要给他分配堆上的内存。

1.myIntArray = new int[3];

2.myIntArray = new int[] { 1, 2, 3 };

3.int[] myIntArray = { 1, 2, 3 };  //当使用这种方法对数组进行初始化时,只能在声明变量数组时使用,不能在声明数组之后使用。

1.4 数组的访问

数组在声明和初始化后,可以使用索引器进行访问,索引器总是以0开头,表示第一个元素。

 //数组调用
string[] stringArray = new string[] { "aa", "bb", "cc" };
Console.WriteLine("stringValue=\"{0}\"", stringArray[0]);
Console.ReadLine();
//运行结果为:
//stringValue="aa"

 1.5数组类型

数组根据维度不同,分为矩阵数组(一维数组,二维数组,多维数组)和锯齿数组(也就是数组的数组),下面看一下他们的声明方式

//数组 声明
string[] stringArray = new string[] { "aa", "bb", "cc" };
//数组 访问
Console.WriteLine("一维数组第一个值为:{0}", stringArray[0]);
//运行结果为:一维数组第一个值为:aa

//二维数组 声明
string[,] stringArray2 = new string[,] { { "a1", "a2", "ac" }, { "b1", "b2", "b3" }, { "c1", "c2", "c3" } };
//二维数组访问
Console.WriteLine("二维数组的1维第1个值是:{0}", stringArray2[0, 0]);
//运行结果为:二维数组1维第1个值为:a1

//三维数组访问 声明
int[, ,] myIntArray3 = new int[,,] {
                { {1,1}, {11,11}, {111,111} },
                { {2,2}, {22,22}, {222,222} },
                { {3,3}, {33,33}, {333,333} },
                { {4,4}, {44,44}, {444,444} }
                };
//三维数组访问 访问
Console.WriteLine("三维数组2维的2维的第2个值为:{0}", myIntArray3[1,1, 1]);
//运行结果为:三维数组2维的2维的第2个值为:22

//锯齿数组(又称数组的数组)
int[][] myIntArray4 = new int[3][];
myIntArray4[0] = new int[] { 1, 11, 111 };
myIntArray4[1] = new int[2] { 2, 22 };
myIntArray4[2] = new int[] { 3, 33, 333, 3333 };
Console.WriteLine("锯齿数组第3个数组的第2个值为:{0}", myIntArray4[2][1]);
//运行结果为:锯齿数组第3个数组的第2个值为:33
Console.ReadLine();

2.集合

2.1.什么时集合?

广义的角度理解集合,就是一组东西聚集在一起。而.NET的集合的定义为:在.NET Framework 中,提供了用于数据存储和检索的专用类,这些类统称集合。这些类提供对堆栈、队列、列表和哈希表的支持。大多数集合类实现相同的接口。

其中最常用的是System.Collections命名空间下的ArrayList,它是按需分配自动增加的实现IList接口的数组。它的默认初始容量为0,因此集合的索引从0开始。

2.2.数组和集合的区别:

在介绍集合前,先说一下集合和数组的区别,既然有了数组,为何C#还要设定一个集合呢?

区别如下:

数组有他的优点,就是在内存中连续存储,遍历比较方便,也可以很方便的修改元素。缺点就是需要指定数组变量大小,此外,两个元素间添加一个元素也比较麻烦。

而集合则不需要事先定义大号,可以根据需要自动分配大小。随意添加移除某一范围元素也比较方法。

2.3 示例:

还是以前面的动物家族为例,说明集合ArrayList的插入,添加,移除操作

  1 /// <summary>
  2 /// 动物类(父类 抽象类)
  3 /// </summary>
  4 abstract class Animal
  5 {
  6     /// <summary>
  7     /// 名字
  8     /// 说明:类和子类可访问
  9     /// </summary>
 10     protected string name;
 11
 12     /// <summary>
 13     /// 构造函数
 14     /// </summary>
 15     /// <param name="name"></param>
 16     public Animal(string name)
 17     {
 18         this.name = name;
 19     }
 20
 21     private int shoutNum = 3;
 22     public int ShoutNum
 23     {
 24         get { return shoutNum; }
 25         set { shoutNum = value; }
 26     }
 27
 28     /// <summary>
 29     /// 名字(虚属性)
 30     /// </summary>
 31     public virtual string MyName
 32     {
 33         get { return this.name; }
 34     }
 35
 36     /// <summary>
 37     /// 叫声,这个方法去掉虚方法,把循环写在这里
 38     /// </summary>
 39     public void Shout()
 40     {
 41         string result = "";
 42         for (int i = 0; i < ShoutNum; i++)
 43             result += getShoutSound() + "!";
 44
 45         Console.WriteLine(MyName);
 46         Console.WriteLine(result);
 47     }
 48
 49     /// <summary>
 50     /// 创建一个叫声的虚方法,子类重写
 51     /// </summary>
 52     /// <returns></returns>
 53     public virtual string getShoutSound()
 54     {
 55         return "";
 56     }
 57 }
 58 /// <summary>
 59 /// 狗(子类)
 60 /// </summary>
 61 class Dog : Animal
 62 {
 63     string myName;
 64     public Dog(string name)
 65         : base(name)
 66     {
 67         myName = name;
 68     }
 69     /// <summary>
 70     /// 名字(重写父类属性)
 71     /// </summary>
 72     public override string MyName
 73     {
 74         get { return "我是:狗狗,我叫:" + this.name; }
 75     }
 76     /// <summary>
 77     /// 叫(重写父类方法)
 78     /// </summary>
 79     public override string getShoutSound()
 80     {
 81         return "汪!";
 82     }
 83 }
 84
 85 /// <summary>
 86 /// 猫(子类)
 87 /// </summary>
 88 class Cat : Animal
 89 {
 90     string myName;
 91     public Cat(string name)
 92         : base(name)
 93     {
 94         myName = name;
 95     }
 96     /// <summary>
 97     /// 名字(重写父类属性)
 98     /// </summary>
 99     public override string MyName
100     {
101         get { return "我是:猫咪,我叫:" + this.name; }
102     }
103     /// <summary>
104     /// 叫(重写父类方法)
105     /// </summary>
106     public override string getShoutSound()
107     {
108         return "喵!";
109     }
110 }
111
112 /// <summary>
113 /// 羊(子类)
114 /// </summary>
115 class Sheep : Animal
116 {
117     string myName;
118     public Sheep(string name)
119         : base(name)
120     {
121         myName = name;
122     }
123     /// <summary>
124     /// 名字(重写父类属性)
125     /// </summary>
126     public override string MyName
127     {
128         get { return "我是:羊羊,我叫:" + this.name; }
129     }
130     /// <summary>
131     /// 叫(重写父类方法)
132     /// </summary>
133     public override string getShoutSound()
134     {
135         return "咩!";
136     }
137 }

调用及返回结果:增加、添加、移除实现示例如下:

 1 //IList 添加、插入元素
 2 IList animalList = new ArrayList();
 3 Cat huaHua = new Cat("花花");
 4 animalList.Insert(0, new Dog("旺财"));//Insert是在指定的索引处插入元素
 5 animalList.Add(new Cat("阿狸"));//Add是在集合最后面插入元素
 6 animalList.Insert(animalList.Count, new Sheep("慢羊羊"));
 7 animalList.Add(huaHua);
 8 //增加四个元素后的返回结果如下
 9 Console.WriteLine("增加四个元素后的返回结果:");
10 foreach (Animal animal in animalList)
11 {
12     animal.Shout();
13 }
14
15 //移除元素
16 //旺财和阿狸退出队列
17 animalList.RemoveAt(0);
18 animalList.RemoveAt(0);//注意这里当移除一个元素后,后面的元素会排到第一位了,移除第二个元素不能是 animalList.RemoveAt(1);
19 animalList.Remove(huaHua);//Remove是指移除指定的元素,注意这里不能animalList.Remove(new Cat("花花"));这样写查找不到,因为new以后又是另一个实例了(另一只同名的猫而已)
20
21 //移除元素后的返回结果如下:
22 Console.WriteLine("增加四个元素后的返回结果:");
23 foreach (Animal animal in animalList)
24 {
25     animal.Shout();
26 }
27 Console.ReadLine();

返回结果:

2.4集合ArrayList的缺点

集合ArrayList相比数组有这么多好处,但是他也是有很多缺点的

A.ArrayList并非类型安全

ArrayList不论什么类型都接受,实际是接受一个object类型。

比如如下操作:

ArrayList ar = new ArrayList();
ar.Add(111);
ar.Add("bbb");

我们使用foreach遍历的时候   foreach(int array in ar){}那么遇到”bbb”则程度报错,因此我们说他是非安全类型。

B.遍历ArrayList资源消耗大

因此类型的非安全,我们在使用ArrayList的时候,就意味着增加一个元素,就需要值类型转换为Object对象。遍历的时候,又需要将Object转为值类型。

就是装箱(boxing,指将值类型转换为引用类型)和拆箱(unboxing,指将引用类型转换为值类型)

由于装箱了拆箱频繁进行,需要大量计算,因此开销很大。如此说来还不如数组来的方便。我们只能说各有利弊,小伙伴们不要急,.net的设计者在2.0以后的版本中为我们解决了上述后顾之忧,那就是下一节要说的泛型。

3.要点:

A.数组是一种数据结构,包含有同类型的多个元素

B..集合是.net中提供数据存储和检索的专用类

C.ArrayList是按需分配自动增加的实现IList接口的数组

D.集合和数组各有优缺点,数组定义需要预先指定大小,而集合虽然不需要事先指定,但是存在类型安全和资源消耗过大的缺陷。

使用泛型可以解决上面的问题。

==============================================================================================

返回目录 <如果对你有帮助,记得点一下推荐哦,有不明白的地方或写的不对的地方,请多交流>

==============================================================================================

时间: 2024-10-24 16:23:24

[.net 面向对象编程基础] (17) 数组与集合的相关文章

[.net 面向对象编程基础] (20) LINQ使用

[.net 面向对象编程基础] (20)  LINQ使用 通过上节LINQ的基础知识的学习,我们可以开始使用LINQ来进行内存数据的查询了,我们上节说了LINQ的定义为:Language Integrated Query(语言集成查询)的简称,它是集成在.NET编程语言中的一种特性. 1.LINQ的构架 从这幅图中,我们可以知道LINQ包括五个部分:LINQ to Objects.LINQ to XML.LINQ to SQL.LINQ to DataSet.LINQ to Entities.

[.net 面向对象编程基础] (18) 泛型

[.net 面向对象编程基础] (18) 泛型 上一节我们说到了两种数据类型数组和集合,数组是指包含同一类型的多个元素,集合是指.net中提供数据存储和检索的专用类. 数组使用前需要先指定大小,并且检索不方便.集合检索和声明方便,但是存在类型安全问题,本来使一个类型安全的C#变得不安全了. 集合为了解决数组预设大小的问题,采取了一种自动扩容的办法,这样当大小不够时,他就创建一个新的存储区域,把原有集合的元素复制过来.如此又对性能上也是有很大的影响. 上节我们说到解决这些缺陷的方法,那就是.NET

[.net 面向对象编程基础] (7) 基础中的基础——流程控制语句

[.net 面向对象编程基础] (7) 基础中的基础——流程控制语句 本来没有这一节的内容,后来考虑到既然是一个系列文章,那么就尽可能写的详细一些,本节参考了网上朋友所写的例子,为的是让更多小伙伴学习,提高,加薪,如有版权问题,请邮件我,我第一时间处理. 语句:是程序中的小指令,本节主要以流程控制语句为主要内容. 流程控制语句中最常用的三个是 选择语句(即条件语句).循环语句和异常处理语句 流程控制语句分类: 类别    关键字 选择语句  if.else.switch.case 循环语句  d

[.net 面向对象编程基础] (16) 接口

[.net 面向对象编程基础] (16) 接口 关于“接口”一词,跟我们平常看到的电脑的硬件“接口”意义上是差不多的.拿一台电脑来说,我们从外面,可以看到他的USB接口,COM接口等,那么这些接口的目的一就是让第三方厂商生产的外设都有相同的标准,也是提供一个对外通信或操作的入口. 只是C#的接口除了以上特点之外,还具有一种类似于模板的功能,我们定义一组接口,就像是一个模板.这点和抽象类不同,抽象类是先有子类或都子类的概念,从中抽象出一个类.而接口更像是我们要设计一台机器,先把这台机器对外的功能接

[.net 面向对象编程基础] (9) 类的成员(字段、属性、方法)

[.net 面向对象编程基础] (9) 类的成员(字段.属性.方法) 前面定义的Person的类,里面的成员包括:字段.属性.方法.事件等,此外,前面说的嵌套类也是类的成员. a.类的成员为分:静态成员(static)和非静态成员 b.静态成员用static标识,不标识则默认为非静态成员 c.静态成员属于类所有,动态成员则属于实例所有,即对象 d.静态成员为类所有实例共享,无论类有多少实例或副本,静态成员只占用存中一块区域.非静态成员则在类的每个实例,都创建一个内存域. 下面主要说明一下类的主要

C#面向对象编程基础-喜课堂笔记

**************[5][C#面向对象编程基础]第1讲:类与对象**************** ????????????????*************2.1.1_类与对象的概念************** ? 研究对象的入口是: 静态特征:-------属性(什么样子) 动态特征:-------方法!(能做什么)这两个也是对象区分的重要因素! 3. 对象表示世界中的实体,面向对象编程就是将这些实体模拟到计算机中! 4. 什么是封装? ????封装是指将一个或多个小对象包装在一起,

[.net 面向对象编程基础] (22) 事件

[.net 面向对象编程基础] (22)  事件 事件(Event)是学习.net面向对象编程很重要的一部分,在学习事件之前,我们实际上已经在很多地方使用了事件,比如控件的click事件等,这些都是.net设计控件的时候已经定义好的事件.除此之外,我们同样可以自己定义事件. 事件实际上是一种消息机制,当然点击控件时,click就通知处理他的方法去处理,实际上就是前面说的委托.因此我们可以说:事件是一种具有特殊签名的委托.而事件/消息机制是windows的核心,因此我们必须掌握他. 为了更加容易理

[.net 面向对象编程基础] (14) 重构

[.net 面向对象编程基础] (14) 重构 通过面向对象三大特性:封装.继承.多态的学习,可以说我们已经掌握了面向对象的核心.接下来的学习就是如何让我们的代码更优雅.更高效.更易读.更易维护.当然了,这也是从一个普通程序员到一个高级程序员的必由之路.就看病一样,普通医生只能治标,高级医生不但看好病,还能除病根. 1.什么时重构? 重构(Refactoring)就是在不改变软件现有功能的基础上,通过调整程序代码改善软件的质量.性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性.

[.net 面向对象编程基础] (21) 委托

[.net 面向对象编程基础] (20)  委托 上节在讲到LINQ的匿名方法中说到了委托,不过比较简单,没了解清楚没关系,这节中会详细说明委托. 1.什么是委托? 学习委托,我想说,学会了就感觉简单的不能再简单了,没学过或都不愿了解的人,看着就头大,其实很简单.委托在.net面向对象编程和学习设计模式中非常重要,是学习.net面向对象编程必须要学会并掌握的. 委托从字面上理解,就是把做一些事情交给别人来帮忙完成.在C#中也可以这样理解,委托就是动态调用方法.这样说明,就很好理解了. 平时我们会