数组
数组
定义
重要细节
数组的类型
数组是对象
一维数组和矩形数组
实例化一维数组或矩形数组
访问数组元素
初始化数组
显式初始化一维数组
显式初始化矩形数组
快捷语法
隐式类型数组
综合内容
交错数组
声明交错数组
快捷实例化
实例化交错数组
比较矩形数组和交错数组
foreach语句
迭代变量是只读的
foreach语句和多维数组
数组协变
数组继承的有用成员
Clone方法
比较数组类型

数组

数组


数组实际上是由一个变量名称表示的一组同类型的数据元素。每个元素通过变量名称和一个或多个方括号中的索引来访问:

数组名  索引↓     ↓
MyArray[4]

定义

让我们从C#中与数组有关的重要定义开始

  • 元素 数组的独立数据项称为元素。数组的所有元素必须是同类型的,或继承自相同的类型
  • 秩/维度 数组可以有任何为正数的维度数。数组的维度数称作秩(rank)
  • 维度长度 数组的每个维度都有一个长度,就是这个方向的位置个数
  • 数组长度 数组的所有维度中的元素的总和称为数组的长度
重要细节

关于C#数组的一些要点:

  • 数组一旦创建,大小就固定了。C#不支持动态数组
  • 数组索引号从0开始。如果维度长度是n,索引号范围就是0到n-1

数组的类型


C#提供两种类型的数组

  • 一维数组可以认为是单行元素或元素向量
  • 多维数组是由主向量中的位置组成的。每个位置本身又是一个数组,称为子数组(subarray)。子数组向量中的位置本身又是一个子数组

另外,有两种类型的多维度数组:矩形数组(rectangular array)和交错数组(jagged array),它们有如下特性:

  • 矩形数组

    • 某个维度的所有子数组具有相同长度的多维数组
    • 不管有多少个维度,总是使用一组方括号 int x=myArray2[4,6,1]
  • 交错数组
    • 每个子数组都是独立数组的多维度数组
    • 可以有不同长度的子数组
    • 为数组的每个维度使用一对方括号 jagArray1[2][7][4]

数组是对象


数组实例是从System.Array继承的对象。由于数组从BCL(Base Class Library)基类继承,它们也继承了很多有用的方法。

  • Rank 返回数组维度数
  • Length 返回数组长度(数组中所有元素的个数)

数组是引用类型,与所有引用类型一样,有数据的引用以及数据对象本身。引用在栈或堆上,而数组对象本身总在堆上。


尽管数组总是引用类型,但是数组元素可以是值类型也可以是引用类型。

  • 如果存储的元素都是值类型,数组被称作值类型数组
  • 如果存储的元素都是引用类型,数组被称作引用类型数组

一维数组和矩形数组


一维数组和矩形数组的语法非常相似,因此放在一起阐述。然后再单独介绍交错数组。

声明一维数组或矩形数组
声明一维数组或矩形数组,在类型和变量名称间使用一对方括号。
矩形数组声明示例:

  • 可以使用任意多的秩说明符
  • 不能在数组类型区域中放数组维度长度。秩是数组类型的一部分,而纬度长度不是类型的一部分
  • 数组声明后,维度数就固定了。然而,纬度长度直到数组实例化时才确定
 秩说明符↓
int[,,] firstArray;     //三维整型数组
int[,]  arr1;           //二维整型数组
long[,] arr3;           //三维long数组
long[3,2,6] SecondArray;//编译错误
       ↑
声明时不允许设置维度长度

和C/C++不同,方括号在基类型后,而不是在变量名称后。

实例化一维数组或矩形数组


要实例化数组,我们可以使用数组创建表达式。数组创建表达式由new运算符构成,后面是基类名称和一对方括号。方括号中以逗号分隔每个维度的长度。

例:

int[] arr2=new int[4];//包含4个int的一维数组
MyClass[] maArr=new MyClass[4];//包含4个MyClass引用的一维数组
int[,,] arr3=new int[3,6,2];//三维数组,数组长度是3*6*2=36

与对象创建表达式不一样,数组创建表达式不包含圆括号-即使是对于引用类型数组。

访问数组元素


在数组中使用整型值作为索引来访问数组元素。

  • 每个维度的索引从0开始
  • 方括号内的索引在数组名称之后
int[] intArr1=new int[15];
intArr1[2]=10;
int var1=intArr1[2];
int[,] intArr2=new int[5,10];
intArr2[2,3]=7;
int var2=intArr2[2,3];

int[] myIntArray;
myIntArray=new int[4];
for(int i=0;i<4;i++)
{myIntArray[i]-i*10;
}
for(int i=0;i<4;i++)
{Console.WriteLine("Value of element {0} = {1}",i,myIntArray[i]);
}

初始化数组


数组被创建后,每个元素被自动初始化为类型的默认值。对于预定义类型,整型默认值是0,浮点型默认值是0.0,布尔型默认值是false,而引用类型默认值则是null。
例:一维数组的自动初始化

int[] intArr=new int[4];

显式初始化一维数组
  • 初始值必须以逗号分隔,并封闭在一组大括号内
  • 不必输入数组长度,因为编译器可以通过初始化值的个数来推断长度
  • 注意,在数组创建表达式和初始化列表中间没有分隔符。即,没有等号或其他连接运算符
int[] intArr=new int[]{10,20,30,40};

显式初始化矩形数组

要显式初始化矩形数组,需遵守以下规则:

  • 每个初始值向量必须封闭在大括号内
  • 每个维度也必须嵌套并封闭在大括号内
  • 除了初始值,每个维度的初始化列表和组成部分也必须使用逗号分隔
int[,] intArray2=new int[,]{{10,1},{2,10},{11,9}};

快捷语法

在一条语句中使用声明、数组创建和初始化时,可以省略语法的数组创建表达式部分。快捷语法如下:

int[] arr1=new int[3]{10,20,30};
int[] arr1=          {10,20,30};
int[,] arr=new int[2,3]{{0,1,2},{10,11,12}};
int[,] arr=            {{0,1,2},{10,11,12}};

隐式类型数组

上面声明的数组都是显式指定数组类型。然而,和其他局部变量一样,数组可以是隐式类型的。

  • 当初始化数组时,我们可以让编译器根据初始化语句的类型来推断数组类型。只要所有初始化语句能隐式转换为单个类型,就可以这么做
  • 和隐式类型的局部变量一样,使用var关键字

虽然用var替代了显式数组类型,但是仍然需要在初始化中提供秩说明符。

int[] intArr1=new int[]{10,20,30,40};
var   intArr2=new    []{10,20,30,40};
int[,] intArr3=new int[,]{{10,1},{2,10},{11,9}};
var    intArr4=new    [,]{{10,1},{2,10},{11,9}};
string[] sArr1=new string[]{"life","liberty","pursuit of happiness"};
var      sArr2=new       []{"life","liberty","pursuit of happiness"};

综合内容

例:综合示例

var arr=new int[,]{{0,1,2},{10,11,12}};
for(int i=0;i<2;i++)
{for(int j=0;j<3;j++){Console.WriteLine("Element [{0},{1}] is {2}",i,j,arr[i,j]);}
}

交错数组


交错数组是数组的数组。与矩形数组不同,交错数组的子数组的元素个数可以不同。

例:二维交错数组

  • 第一个维度长度是3
  • 声明可以读作“jagArr是3个int数组的数组”
  • 图中有4个数组对象-其中一个针对顶层数组,另外3个针对子数组
int[][] jagArr=new int[3][];

声明交错数组

交错数组的声明语法要求每个维度都有一对独立的方括号。数组变量声明中的方括号数决定了数组的秩。
和矩形数组一样,维度长度不能包括在数组类型的声明部分。

int[][] SomeArr;//秩等于2
int [][][] OhterArr;//秩等于3

快捷实例化

我们可以将数组创建表达式创建的顶层数组和交错数组的声明相结合。

int[][] jagArr=new int[3][];//3个子数组

不能在声明语句中初始化顶层数组之外的数组。

int[][] jagArr=new int[3][4];//不允许,编译错误

实例化交错数组

和其他类型数组不一样,交错数组的完全初始化不能在一个步骤中完成。由于交错数组是独立数组的数组-每个数组必须独立创建。

  1. 首先,实例化顶层数组
  2. 其次,分别实例化每个子数组,把新建数组的引用赋给它们所属数组的合适元素

例:实例化交错数组

int[][] Arr=new int[3][];
Arr[0]=new int[]{10,20,30};
Arr[1]=new int[]{40,50,60,70};
Arr[3]=new int[]{80,90,100,110,120};

比较矩形数组和交错数组


矩形数组和交错数组的结构区别非常大。
例如,下图演示了3X3的矩形数组以及由3个长度为3的一维数组构成的交错数组的结构。

  • 两个数组都保存9个整数,但是它们结构很不相同
  • 矩形数组只有1个数组对象,而交错数组有4个数组对象


在CIL(Common Intermediate Laguage,公共中间语言)中,一维数组有特定的指令用于性能优化。矩形数组没有这些指令,并且不在相同级别进行优化。因此,有时使用一维数组(可以被优化)的交错数组比矩形数组(不能被优化)更有效率。
另一方面,矩形数组的编程复杂度要小得多,因为它会被作为一个单元而不是数组的数组。

foreach语句


foreach语句允许我们连续访问数组中的每个元素。
有关foreach语句的重点如下:

  • 迭代变量是临时的,并且和数组中元素的类型相同。foreach语句使用迭代变量来相继表示数组中的每个元素
  • foreach语句的语法如下
    • Type是数组中元素的类型。我们可以显式提供它的类型,或者使用var
    • Identifier是迭代变量名
    • ArrayName是数组名
    • Statement是要为数组中每个元素执行一次的单条语句或语句块
foreach(Type Identifier in ArrayName)//显式
{Statement
}
foreach(var Identifier in ArrayName)//隐式
{Statement
}

foreach如下方式工作:

  • 从数组第一个元素开始并把它赋值给迭代变量
  • 执行语句主体。在主体中,我们可以把迭代变量作为数组元素的只读别名
  • 主体执行后,foreach语句选择数组中的下一个元素并重复处理

例:foreach示例

int[] arr1={10,11,12,13};
foreach(int item in arr1)
{Console.WriteLine("Item Value: {0}",item);
}

迭代变量是只读的

迭代变量是只读的。但是,对于值类型数组和引用类型数组效果不一样。
对于值类型数组,这意味着在用迭代变量时,我们不能改变它们。

例:尝试修改迭代变量报错

int[] arr1={10,11,12};
foreach(int item in arr1)
{item++;
}

对于引用变量,迭代变量保存的是数据的引用,而不是数据本身。所以,我们虽然不能改变引用,但是我们可以改变数据。

例:引用变量修改迭代变量

class MyClass
{public int MyField=0;
}
class Program
{static void Main(){MyClass[] mcArray=new MyClass[4];for(int i=0;i<4;i++){mcArray[i]=new MyClass();mcArray[i].MyField=i;}foreach(var item in mcArray){item.MyField+=10;}foreach(var item in mcArray){Console.WriteLine("{0}",item.MyField);}}
}

foreach语句和多维数组

多维数组里,元素处理顺序是从最右边的索引号依次递增。

例:矩形数组示例

class Program
{static void Main(){int total=0;int[,] arr1={{10,11},{12,13}};foreach(var element in arr1){total+=element;Console.WriteLine("Element:{0},Current Total:{1}",element,total);}}
}

例:交错数组示例

class Program
{static void Main(){int total=0;int[][] arr1=new int[2][];arr1[0]=new int[]{10,11};arr1[1]=new int[]{12,13,14};foreach(int[] array in arr1){Console.WriteLine("Starting new array");foreach(int item in array){total+=element;Console.WriteLine("Item:{0},Current Total:{1}",item,total);}}}
}

数组协变


某些情况下,即使某对象不是数组的基类型,我们也可以把它赋给数组元素。这种属性叫做数组协变(array covariance)。在下面情况下使用数组协变。

  • 数组是引用类型数组
  • 在赋值的对象类型和数组基类之间有隐式转换或显式转换

由于派生类和基类之间总有隐式转换,因此总是可以把派生类对象赋值给基类声明的数组。

例:派生类、基类 数组协变

class A{...}
class B:A{...}
class Program
{static void Main(){A[] AArray1=new A[3];A[] AArray2=new A[3];AArray1[0]=new A();AArray1[1]=new A();AArray1[2]=new A();AArray2[0]=new B();AArray2[1]=new B();AArray2[2]=new B();}
}

值类型数组没有协变

数组继承的有用成员


C#数组从System.Array类继承。它们从基类继承了很多有用的属性和方法。

public static void PrintArray(int[] a)
{foreach(var x in a){Console.WriteLine("{0}",x);}Console.WriteLine("");
}
static void Main()
{int[] arr=new int[]{15,20,5,25,10};PrintArray(arr);Array.Sort(arr);PrintArray(arr);Array.Reverse(arr);PrintArray(arr);Console.WriteLine();Console.WriteLine("Rank = {0},Length = {1}",arr.Rank,arr.Length);Console.WriteLine("GetLength(0)      = {0}",arr.GetLength(0));Console.WriteLine("GetType()         = {0}",arr.GetType());
}

Clone方法

Clone方法为数组进行浅复制。即,它只创建了数组本身的克隆。如果是引用类型数组,它不会复制元素引用的对象。对于值类型数组和引用类型数组,效果不同。

  • 克隆值类型数组会产生两个独立数组
  • 克隆引用类型数组会产生指向相同对象的两个数组

Clone方法返回object类型的引用,它必须被强制转换成数组类型。

int[] intArr1={1,2,3};
int[] intArr2=(int[])intArr1.Clone();

例:Clone值类型数组示例

class Program
{static void Main(){int[] intArr1={1,2,3};int[] intArr2=(int[])intArr1.Clone();intArr2[0]=100;intArr2[1]=200;intArr2[2]=300;}
}

例:Clone引用类型数组示例

class A
{public int Value=5;
}
class Program
{static void Main(){A[] AArray1=new A[3]{new A(),new A(),new A()};A[] AArray2=(A[])AArray1.Clone();AArray2[0].Value=100;AArray2[1].Value=200;AArray2[2].Value=300;}
}

比较数组类型


下表总结了3中类型数组的重要相似点和不同点。

转载于:https://www.cnblogs.com/moonache/p/6255327.html

C#图解教程 第十二章 数组相关推荐

  1. 谭浩强c语言不讲位运算呢,谭浩强C语言教程第十二章-位运算.doc

    谭浩强C语言教程第十二章-位运算 12位运算1 12.1位运算符C语言提供了六种位运算符:1 12.1.1按位与运算1 12.1.2按位或运算2 12.1.3按位异或运算2 12.1.4求反运算3 1 ...

  2. vtk教程第十二章 应用

    我们已经描述了一个广泛的可视化技术工具包的设计和实现.在本章中,我们将研究几个案例研究,以展示如何使用这些工具来深入了解重要的应用领域.这些领域包括医学成像.金融可视化.建模.计算流体动力学.有限元分 ...

  3. C#图解教程 第二十五章 其他主题

    其他主题 概述 在本章中,我会介绍使用C#时的一些重要而又不适合放到其他章节的主题,包括字符串操作.可空类型.Main方法.文档注释以及嵌套类型. 字符串 对于内部计算来说0和1很适合,但是对于人类可 ...

  4. c#中接口的使用方法图解_C#图解教程 第十五章 接口

    接口 什么是接口 接口是指定一组函数成员而不实现它们的引用类型.所以只能类和结构来实现接口. 这种描述比较抽象,直接来看个示例. 下例中,Main方法创建并初始化了一个CA类的对象,并将该对象传递给P ...

  5. 单片机c语言置位程序流程图,单片机c语言教程第十二章--C51开关分支语句

    学习了条件语句,用多个条件语句能实现多方向条件分支,但是能发现使用过多的 条件语句实现多方向分支会使条件语句嵌套过多,程序冗长,这样读起来也很不好读.这个时候 使用开关语句同样能达到处理多分支选择的目 ...

  6. [AJava]FusionCharts Free中文开发指南[使用文档教程]第十二章--FCF中的特殊字符

    在FCF里,如果要在图形里用到一些特殊的字符,你就要对它进行编码,否则就无法显示. 欧元符号在FCF里显示"€",你需要用"%80"来替换它.如下: <g ...

  7. iPhone开发基础教程笔记(十二)--第十二章 使用Quartz和OpenGL绘图

    第十二章 使用Quartz和OpenGL绘图 有时应用程序需要能够自定义绘图.一个库是Quartz 2D,她是Core Graphics框架的一部分:另一个库是OpenGL ES,她是跨平台的图形库. ...

  8. 《Dreamweaver CS6 完全自学教程》笔记 第十二章:框架的应用

    文章目录 第十二章:框架的应用 12.1 创建框架或框架集 12.1.1 创建自定义框架 12.1.2 创建预定义框架 技术专题:框架的拆分与合并 12.1.3 创建嵌套框架 12.2 框架和框架集的 ...

  9. 小菜鸡的html初步教程(第十二章 初步构建响应式网站)

    小菜鸡的第三篇博客  今天是3/19,天气不错,跑到自习室来更新博客. 本系列文章仅仅是对基础的HTML5以及CSS进行讲解,更加详细的内容均会附上链接,以便查阅和版权保护.  昨晚我思考了下,决定对 ...

最新文章

  1. Tutorial——使用Maven开发Cloud Driver
  2. 表格字段居左居右规范_Excel之规范数据
  3. php yii框架路由,yii框架路由配置
  4. 机器学习算法-随机森林之决策树R 代码从头暴力实现(2)
  5. 【转载】4412开发板、PC、ubuntu通过网线连接
  6. 关于微信小程序使用获取用户信息getUserProfile的问题:TypeError: wx.getUserProfile is not a function
  7. css实现动态箭头_Jerry的反省:程序员不要轻易说出quot;这个功能技术上无法实现quot;...
  8. jaspersoft studio6.x 设计医院检查报告单样式
  9. 应急响应-winlinux分析后门勒索病毒攻击
  10. 陈越微博c语言自学攻略,数据结构自学攻略
  11. R语言做生信分析系列(一)—— R软件简单安装
  12. android极光推送tag,Android极光推送设置别名和标签
  13. 从入门到精通!一个三非渣本的Android校招秋招之路,终局之战
  14. calcbusiness使用教程_Calc Business
  15. 九龙证券|人工智能+国产软件+智慧城市概念股火了,欧洲资管巨头大举抄底
  16. UVa 10934 Dropping water balloons:dp(递推)
  17. 如何指定网站内搜索关键字(借用已有搜索引擎)
  18. 虚拟机中Centos更新内核
  19. 四面阿里Java高级研发岗,定级P7:数据结构+分布式+JVM+线程
  20. Java中的专业术语

热门文章

  1. 张爱玲《小团圆》的备忘和感想 (一)
  2. 我在河南安阳拍摄的一个山村小孩儿
  3. 看日本雅-miyavi演唱会
  4. 奇异递归模板模式(Curiously Recurring Template Pattern,CRTP)
  5. hi3798mv300是什么手机_华为海思电视芯片hi3798mv300 硬件参数如何?
  6. 代码统计工具有哪几种_跟我学“Linux”小程序Web版开发(四):引入统计及Crash收集...
  7. 充电原理_电动汽车充电桩如何设置?充电桩原理介绍
  8. mysql主从配置常见问题_mysql 主从复制配置,以及常见问题解决!
  9. AOP集成防止连续多次点击问题
  10. Net EF to MySQL生成edmx文件时报错:StrongTypingException:表“TableDetails中列“IsPrimaryKey的值为DBNull...