C#图解教程 第十二章 数组

数组
数组
定义
重要细节
数组的类型
数组是对象
一维数组和矩形数组
实例化一维数组或矩形数组
访问数组元素
初始化数组
显式初始化一维数组
显式初始化矩形数组
快捷语法
隐式类型数组
综合内容
交错数组
声明交错数组
快捷实例化
实例化交错数组
比较矩形数组和交错数组
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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/255646.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据库学习】——windows、MySQL构建新闻管理系统(控制台版)

学习记录&#xff1a;【Python项目实战】PythonMySQL开发新闻管理系统全集_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Qb4y1b75q?p2&spm_id_frompageDriver 目录 一、项目介绍 1、项目结构 2、系统部分功能提前展示 3、项目流程图 4、项目设计的数据库以及…

微信红包API接口(PHP)

发布时间&#xff1a;2015年2月25日 / 分类&#xff1a;WEB开发,PHP / 74,825 / 241 ℃ 根据微信高级红包接口&#xff0c;开发PHP版本的API接口&#xff0c;现在进行主要代码分析。 红包接口调用请求代码&#xff0c;所有请求参数为必填参数与文档对应&#xff1a; 1234567891…

2016年个人技术总结(前端)

自我总结 参与项目 备注:[☆-表示比较吊的项目,-从头开始做,^-中间加入项目] 神马生活(微信公众号商城)[^] 神马学院[] <!------跳槽线--------> 大数据套件[☆][^] fable数据营销平台(加入新功能&#xff0c;交互)[^] fit问卷系统[] fit投放系统[] fit画像[^] 理财通点击…

彩色CCD相机工作原理

原理 黑白&#xff08;单色&#xff09;相机 CCD原理并不复杂。我们可以把它想象成一个顶部被打开的记忆芯片。因此光束可以射到记忆单元中。根据"光电效应”&#xff0c;这些光束在记忆单元中产生负电荷&#xff08;下图中右上部分&#xff09;。 曝光后&…

【HTML学习】——HTML常见标签属性和方法介绍

目录 1、HTML分块--------< div> 2、HTML段落--------< p> 3、HTML标题--------< h1>…< h6> 4、HTML链接--------< a> 1)< a href“http://www.baidu.com”>百度< /a>&#xff08;点击百度&#xff0c;直接跳转到网页&#xf…

开发者应警惕的七种糟糕职业规划错误

那些心灵鸡汤式的说辞总爱美化失败&#xff1a;失败是成功之母啦、失败使人成长啦、别畏惧失败等等。但事实上&#xff0c;这种思路在软件开发领域也许并不适用——至少不完全适用。每位开发者在职业生涯中都不可避免会遭遇失败&#xff0c;但为什么不从他人的经验中汲取教训来…

【HTML学习】——一个网页HTML编程的构成

目录 1、html网页构成介绍 2、HTML标签介绍 全部的html标签&#xff1a; HTML: HyperText Markup Language | MDNhttps://developer.mozilla.org/en-US/docs/Web/HTML 一个网页文件一般由.html结尾的文件组成&#xff0c;主要由不同的标签对和内容组成&#xff0c;常见的html…

hbase里插入big int数据用Phoenix查看的报错问题

Phoenix建表create table "test_big_int"("ROW" varchar primary key,"ci"."column1" bigint) 在hbase里put数据hbase 里面进行put: put test_big_int,001,ci:column1,1 在Phoenix里进行查看&#xff08;问题出现&#xff09;第二个尝…

机器学习:利用卷积神经网络实现图像风格迁移 (一)

相信很多人都对之前大名鼎鼎的 Prisma 早有耳闻&#xff0c;Prisma 能够将一张普通的图像转换成各种艺术风格的图像&#xff0c;今天&#xff0c;我们将要介绍一下Prisma 这款软件背后的算法原理。就是发表于 2016 CVPR 一篇文章&#xff0c; “ Image Style Transfer Using Co…

博客园自定义样式

碎碎念&#xff1a; 已经很长时间没有更新过博客了&#xff0c;分析一下&#xff0c;一个是太懒了。。。所以很久没整理一下了。还有就是嫌弃博客园默认的博客界面真的太丑了&#xff0c;作为颜控的我真的无法忍受啊。个人比较喜欢用makedown来编写博客&#xff0c;但是博客园自…

【CSS】——cascading stylesheets层叠式样式表

目录 0、CSS介绍 1、CSS语句组成 2、CSS选择器的选择方式 1&#xff09;CSS选择器的方式和选择器大全&#xff1a; 2&#xff09;常见的三种方式&#xff1a; 3、添加CSS方式 1&#xff09;外部样式表 html调用css代码 css文件 html文件 展示 2&#xff09;内部样式表…

四 Apache Axis2 部署 WebService

最新版本1.7.4发布日期2016-10-21 Axis2官网下载如下文件&#xff1a; axis2-1.6.2-bin&#xff1a;二进制的axis axis2-1.6.2-docs&#xff1a;帮助文档 axis2-1.6.2-war&#xff1a;axis.war 文件 axis2-eclipse-codegen-plugin-1.6.2&#xff1a;Eclipse axis client 插件 a…

安装OpenCV:OpenCV 2.4.8或OpenCV 2.4.9 +VS 开发环境配置

因为读研期间的研究方向是图像处理&#xff0c;所以浅墨这段时间闭门研究了很多OpenCV和图像处理相关的知识与内容。眼看自己积累到一定的程度了&#xff0c;于是决定开始开设这个OpenCV系列专栏&#xff0c;总结自己所学&#xff0c;也分享知识给大家。 好了&#xff0c;这篇文…

powerdesigner中如何在自动生成建表SQL时添加模式名schema

1、在主菜单中选择“模型”→“users and roles”→“users”&#xff0c;新增一个user&#xff0c;其中"name"字段就是要添加的模式名。 2、在新增表时&#xff0c;在表属性的“general”页签中选择"owner"&#xff0c;选择刚才新增的user&#xff0c;即可…

【django学习】——Django介绍和实战(开发简易版博客网页)

目录 0、视频链接 1、环境配置 2、django基本命令 1&#xff09;常见命令 2&#xff09;数据库相关的Django命令 3、Django项目 1&#xff09;Django创建项目 2&#xff09;项目目录介绍 3&#xff09;运行初始化的Django项目 4、Django应用 1&#xff09;Django项目和Djan…

求最大子数组03

题目: 返回一个二维整数数组中最大联通子数组的和。 要求&#xff1a; 1. 输入一个二维整形数组&#xff0c;数组里有正数也有负数。 求所有子数组的和的最大值。要求时间复杂度为O(n)。 2.程序要使用的数组放在一个叫 input.txt 的文件中&#xff0c; 文件格式是: 数组的行…

纠错——【Singleton array array(0.2) cannot be considered a valid collection.】

# 将数据集按照比例划分为训练集和测试集 def split_datas(datas,labels,random_state1,train_size0.9,test_size0.1):train_data, test_data, train_label, test_label sklearn.model_selection.train_test_split(datas,labels,random_staterandom_state,# 作用是通过随机数来…

Android Studio 模拟器 不要皮肤,效果更好

新建或者编辑虚拟机时&#xff0c;皮肤选择“No Skin”即可&#xff0c;第二张图片就是无皮肤的效果&#xff0c;看着更爽啊。 转载于:https://www.cnblogs.com/toSeeMyDream/p/6265501.html

JAVA 笔记(三)

NullPointerException:空指针异常 原因&#xff1a;数组已经不再指向堆内存了。而你还用数组名去访问元素。对于查找问题&#xff0c;如果找到就返回其索引值&#xff0c;如果找不到就要返回一个负数&#xff08;一般是负一&#xff09;这是必须的&#xff0c;否则如果找不到&a…

安装Wamp后 Apache无法启动的解决方法

安装Wamp后 Apache无法启动的解决方法&#xff0c;网上的解决方案可以说是五花八门&#xff0c;有些说了一大推&#xff0c;一点作用都起不到。 其实解决方法只需两步&#xff1a; 1、安装路径不能包含有中文&#xff0c;这个我不知道为什么&#xff0c;总之如果安装路径中包含…