阅读本文大概需要 1.5 分钟。

数组本身相对来说比较简单,能想到的可写的东西不多。但还是有一些知识点值得总结和知晓一  下。有的知识点,知不知道不重要,工作中用的时候搜索一下就可以了,毕竟实现一个功能代码的写法有很多种,再牛的人也不可能完全熟悉一门语言的每个细节。当然了,偶然地知道了一些小知识或小技巧也是一种小小的收获。在你看这篇小文时,或许这种偶然的事情就正在发生。我们先从数组的初始化开始吧。

数组的定义和初始化

定义和初始化一个数组有好几种方式,随着 C# 版本升级,方式也越来越简单:

int[] arr = new int[3];           // 定义一个长度为 3 的数组
int[] arr = new int[3] {1, 2, 3}; // 定义一个长度为 3 的数组并初始化
int[] arr = new [] {1, 2, 3}; // 上面的简写
int[] arr = {1, 2, 3}; // 上面的进一步简写

我们知道当定义一个固定长度的数组没有初始化时,比如:

int[] arr = new int[3];

虽然没有初始化,但它是有默认值的,这个数组中包含了 3 个值为 0 的整数。如何使用非默认值创建一个数组呢?可以使用 System.Linq 命名空间下的 Enumerable.Repeat 方法:

// 创建长度为 5 的整形数组,并用 100 来填充
int[] arr = Enumerable.Repeat(100, 5).ToArray(); // 创建长度为 5 的字符串数组,并用“C#”来填充
string[] arr = Enumerable.Repeat("C#", 5).ToArray();

数组的复制、克隆与比较

把一个数组的元素复制到另一个数组,可以使用 Array.Copy() 方法,复制时源数组取值和目标数组赋值都是从索引 0 开始的:

var sourceArray = new int[] { 11, 12, 3, 5, 2, 9};
var destinationArray = new int[3];
Array.Copy(sourceArray, destinationArray, 3);
// destinationArray = [11, 12, 3]

克隆一个数组很简单:

var sourceArray = new int[] { 11, 12, 3 };
var destinationArray = (int[])sourceArray.Clone();
// destinationArray = [11, 12, 3]

比较两个数组是否一样,即两个数组包含的元素及元素的顺序是否都一样,可以使用数组的 SequenceEqual 方法:

int[] arr1 = { 3, 5, 7 };
int[] arr2 = { 3, 5, 7 };
bool result = arr1.SequenceEqual(arr2); // true

以上只是罗列几个有代表性的比较快捷简单的数组操作,在 C# 中借助 Linq 可以实现更复杂的数组操作,这里先不作总结。

使用指针遍历数组

实际的 C#开发中很少会直接用到指针,在需要进行底层操作时可能会用到。在 C# 中使用指针时需要在 unsafe 上下文中操作:

int[] arr = new int[] {1, 6, 3, 3, 9};

// 使用 foreach
foreach (int element in arr)
{
Console.WriteLine(element);
} // 使用指针
unsafe
{
int length = arr.Length;
fixed (int* p = arr)
{
int* pInt = p;
while (length-- > 0)
{
Console.WriteLine(*pInt);
pInt++; // 将指针移到下一个元素
}
}
}
// 依次输出:1 6 3 3 9

这里只是让大家知道有这么一回事,指针不是本篇的话题,更多关于指针的操作可以访问:

https://bit.ly/2MmIsNl

生成有序数组

我就见过有人使用 for 循环生成一个从 n 到 m 的有序数组,其实 C# 提供了 Enumerable.Range 方法可以很容易地创建一个有序的整型数组。示例:

// 创建数字从 1 到 100 的数组
int[] sequence = Enumerable.Range(1, 100).ToArray(); // 结合 Linq 还可以实现更复杂的数组创建逻辑
int[] squares = Enumerable.Range(2, 10).Select(x => x * x).ToArray(); // 3, 9, 16...

多维数组和交错数组的区别

简单来说,多维数组每一行长度都是固定的,比如二维数组是一个 m 行 n 列的矩阵:

int[,] arr = {
{1, 2, 3, 4},
{4, 2, 1, 3},
{2, 1, 3, 4},
}

而交错数组(又叫锯齿数组)的每一行可以有不同的大小,表示的是数组的数组。比如:

int[][] arr = {
new [] {1, 2, 3, 4},
new [] {1, 2},
new [] {1, 2, 3},
}

它们的定义、初始化、取值、赋值等都有明显的区别。

先看多维数组:

// 多维数组的定义
int[,] arr = new int[10, 10]; // 二维数组
int[,,] arr = new int[10, 10, 10]; // 三维数组 // 多维数组的初始化 (new int[3, 2] 可以省略)
int[,] arr = new int[3, 2] { {1, 1}, {2, 2}, {3, 3} }; // 多维数组的取值
Console.WriteLine(arr[2, 1]); // 3 // 多维数组的赋值
arr[2, 1] = 10;

再对比交错数组:

// 交错数组的定义
int[][] arr = new int[10][]; // 二层:数组的数组
int[][][] arr = new int[10][][]; // 三层:数组的数组的数组 // 交错数组的初始化 (new int[3][] 可以省略)
int[][] arr = new int[3][] { new [] {1}, new [] {2, 2}, new [] {3, 3, 3} }; // 交错数组的取值
Console.WriteLine(arr[2][1]); // 3 // 多维数组的赋值
arr[2][1] = 10;

注意:多维数组每行长度必须一致;交错数组第二个 [] 是不能有数字的。两者的 Length 属性意义也是不一样的,多维数组的 Length 属性取的是数组所有元素的总数,而交错数组取的是第一层的数组的个数。例如:

int[,] arr1 = new int[3, 2] { { 1, 1 }, { 2, 2 }, { 3, 3 } };
Console.WriteLine(arr1.Length); // 输出:6 int[][] arr2 = new int[3][] { new[] { 1 }, new[] { 2, 2 }, new[] { 3, 3, 3 } };
Console.WriteLine(arr2.Length); // 输出:3

建议:除了某些像矩阵这样的操作场景可能更适合使用多维数组,大多数场景应尽量选择使用交错数组。功能上多维数组可以实现的,交错数组也都能实现,反过来不一定可以。另外,根据 stackoverflow 网友的回答(下面参考链接),在 .NET 中,交错数组性能上要好于多维数组。

参考:https://bit.ly/2Mqn6P1

[C#.NET 拾遗补漏]02:数组的几个小知识的更多相关文章

  1. golang拾遗:内置函数len的小知识

    len是很常用的内置函数,可以测量字符串.slice.array.channel以及map的长度/元素个数. 不过你真的了解len吗?也许还有一些你不知道的小知识. 我们来看一道GO101的题目,这题 ...

  2. [C#.NET 拾遗补漏]11:最基础的线程知识

    线程的知识太多,知识点有深有浅,往深的研究会涉及操作系统.CUP.内存,往浅了说就是一些语法.没有一定的知识积累,很难把线程的知识写得全面,当然我也没有这个能力.所以想到一个点写一个点,尽量总结一些有 ...

  3. [C#.NET 拾遗补漏]05:操作符的几个骚操作

    阅读本文大概需要 1.5 分钟. 大家好,这是极客精神[C#.NET 拾遗补漏]专辑的第 5 篇文章,今天要讲的内容是操作符. 操作符的英文是 Operator,在数值计算中习惯性的被叫作运算符,所以 ...

  4. [C#.NET 拾遗补漏]07:迭代器和列举器

    大家好,这是 [C#.NET 拾遗补漏] 系列的第 07 篇文章. 在 C# 中,大多数方法都是通过 return 语句立即把程序的控制权交回给调用者,同时也会把方法内的本地资源释放掉.而包含 yie ...

  5. [C#.NET 拾遗补漏]08:强大的LINQ

    大家好,这是 [C#.NET 拾遗补漏] 系列的第 08 篇文章,今天讲 C# 强大的 LINQ 查询.LINQ 是我最喜欢的 C# 语言特性之一. LINQ 是 Language INtegrate ...

  6. [C#.NET 拾遗补漏]06:单例模式实佳实践

    大家好,这是[C#.NET 拾遗补漏]专辑的第 06 篇文章.今天讲讲大家熟悉的单例模式. 单例模式大概是所有设计模式中最简单的一种,如果在面试时被问及熟悉哪些设计模式,你可能第一个答的就是单例模式. ...

  7. 055 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 02 数组的概念

    055 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 02 数组的概念 本文知识点:数组的概念 数组的声明创建.初始化 在学习数组的声明创建.初始化前,我们可以和之 ...

  8. Swift初探02 数组、集合、元组、字典

    数组.集合.元组.字典 每一门语言基本都会有这些数据结构,swift也不例外,而作为一门现代的语言,swift提供了很多的现成的方法给我们选择. 一.数组 01 数组的定义 // 三种声明方式 var ...

  9. [C#.NET 拾遗补漏]03:你可能不知道的几种对象初始化方式

    阅读本文大概需要 1.2 分钟. 随着 C# 的升级,C# 在语法上对对象的初始化做了不少简化,来看看有没有你不知道的. 数组的初始化 在上一篇罗列数组的小知识的时候,其中也提到了数组的初始化,这时直 ...

随机推荐

  1. zsteg

    以前知道zsteg,但是没有去安装使用,所以就一直没有使用. 最近在找有关lsb隐写的题,发现有些大佬的wp上面写用zsteg就解决了lsb隐写的题,自己就想,难道zsteg很方便,于是就去安装zst ...

  2. resize允许你控制一个元素的可调整大小性

  3. vue+express上传头像到数据库中img的路径

    项目结构 express中间件指定静态资源目录 app.use("/static",express.static(path.join(__dirname,"/public ...

  4. 1.2Go环境搭建之Mac

    1.下载mac版go开发工具包,源码包或是安装包都可以 //官方下载地址 https://golang.org/dl/ //下载地址在此 https://dl.google.com/go/go1.11 ...

  5. Django操作cookie实例

     cookie项目文件: templates模板: login.html {% load static %} <!DOCTYPE html> <html lang="en& ...

  6. 移动端在ios上以及微信浏览器上的兼容性

    1.document.以及window.body在移动h5不能触发点击事件 解决方法:给body加上cursor: pointer;就可以有点击事件了. ios上默认的body是没有点击事件的: 接着 ...

  7. 【项目练习】thinkphp用户注册

    使用mvc,ajax 路由 //后台登陆 Route::group('admin', function () { Route::rule('login', 'admin/Index/login'); ...

  8. Linux下VCS2014和Verdi2015的联合使用

    VCS和Verdi是IC设计中常用的两款开发工具.VCS是Synopsys公司的产品,和大家所熟知的ModeSim一样的都是EDA仿真工具.Verdi是Nocas公司(已经被Synopsys公司收购) ...

  9. SpringBoot自定义装配的多种实现方法

    Spring手动装配实现 对于需要加载的类文件,使用@Configuration/@Component/@Service/@Repository修饰 @Configuration public cla ...

  10. 实验三:Linux系统用户管理及VIM配置

    项目 内容 这个作业属于哪个课程 班级课程的主页链接 这个作业的要求在哪里 作业要求链接地址 学号-姓名 17043133-木腾飞 学习目标 1.学习Linux系统用户管理2.学习vim使用及配置 实 ...