1. 数组隐式继承 System.Array,所以数组是引用类型。变量包含的是对数组的引用,而不是包含数据本身的元素。

2. 数组协变性。将数组从一种类型转换为另一种类型。

string[] sa = new string[100];
object[] oa = sa;
oa[5] = "Jeff"; // 性能损失:CLR检查oa的元素类型是不是String;检查通过
oa[3] = 5; // 性能损失:CLR检查oa的元素类型是不是Int32;发现有错,抛异常

System.Buffer的BlockCopy方法,只支持基元类型,不具有转型能力。

System.Array的ConstrainedCopy方法,要么完美复制,要么抛出异常,不会破坏目标数组中的数据,不执行装箱、拆箱和向下类型转换。

3. 所有数组都隐式实现 IEnumerable,ICollection,IList

4. 创建下限非0的数组

int[] lowerBounds = { 2015, 1 };
int[] lengths = { 5, 4 };
decimal[,] quarterlyRevenue = (decimal[,])Array.CreateInstance(typeof(decimal), lengths, lowerBounds);
Console.WriteLine("{0,4} {1,9} {2,9} {3,9} {4,9}", "year", "Q1", "Q2", "Q3", "Q4");
int fristYear = quarterlyRevenue.GetLowerBound(0); // 2015
int lastYear = quarterlyRevenue.GetUpperBound(0); // 2019
int fristQuarter = quarterlyRevenue.GetLowerBound(1); // 1
int lastQuarter = quarterlyRevenue.GetUpperBound(1); // 4
for (int year = fristYear; year <= lastYear; year++)
{
Console.Write(year + " ");
for (int quarter = fristQuarter; quarter < lastQuarter; quarter++)
{
Console.Write("{0,9:C} ", quarterlyRevenue[year, quarter]);
}
Console.WriteLine();
}

5. 数组只有两种,下限为0的一维数组(System.String[])和下限未知的多维数组(System.String[,])。1维1基数组(System.String[*])C#不允许使用。访问一维0基数组比访问非0基多维数组要快,因为在for循环中JIT编译器会生成代码来检查是否 0 >= GetLowerBound(0) && (length-1) <= GetUpperBound(0),一维0基数组只会在for循环前检查1次,非0基多维数组则每次都会检查。

private const int c_numElements = 10000;
public static void Main()
{
int[,] a2Dim = new int[c_numElements, c_numElements];
int[][] aJagged = new int[c_numElements][];
for (int x = 0; x < c_numElements; x++)
{
aJagged[x] = new int[c_numElements];
} Safe2DimArrayAccess(a2Dim); SafeJaggedArrayAccess(aJagged); Unsafe2DimArrayAccess(a2Dim);
}
private static int Safe2DimArrayAccess(int[,] a)
{
int sum = 0;
for (int x = 0; x < c_numElements; x++)
{
for (int y = 0; y < c_numElements; y++)
{
sum += a[x, y];
}
}
return sum;
}
private static int SafeJaggedArrayAccess(int[][] a)
{
int sum = 0;
for (int x = 0; x < c_numElements; x++)
{
for (int y = 0; y < c_numElements; y++)
{
sum += a[x][y];
}
}
return sum;
}
private static unsafe int Unsafe2DimArrayAccess(int[,] a)
{
int sum = 0;
fixed (Int32* pi = a)
{
for (int x = 0; x < c_numElements; x++)
{
int baseOfDim = x * c_numElements;
for (int y = 0; y < c_numElements; y++)
{
sum += pi[baseOfDim + y];
}
}
}
return sum;
}

6. 栈上分配数组

public static void Main()
{
StackallocDemo();
InlineArrayDemo();
}
private static void StackallocDemo()
{
unsafe
{
const int width = 20;
Char* pc = stackalloc char[width]; // 在栈上分配数组
string s = "Jeffrey Richter";
for (int index = 0; index < width; index++)
{
pc[width - index - 1] = (index < s.Length) ? s[index] : '.';
}
Console.WriteLine(new string(pc, 0, width));
}
} private static void InlineArrayDemo()
{
unsafe
{
CharArray ca;
Int32 widthInByBytes = sizeof(CharArray);
Int32 width = widthInByBytes / 2; string s = "Jeffrey Richter";
for (int index = 0; index < width; index++)
{
ca.Characters[width - index - 1] = (index < s.Length) ? s[index] : '.';
}
Console.WriteLine(new string(ca.Characters, 0 ,width));
}
} internal unsafe struct CharArray
{
public fixed Char Characters[20];
}

CLR via C# 笔记 -- 数组(16)的更多相关文章

  1. <NET CLR via c# 第4版>笔记 第16章 数组

    //创建一个一维数组 int[] myIntegers; //声明一个数组引用 myIntegers = new int[100]; //创建含有100个int的数组 //创建一个二维数组 doubl ...

  2. Flutter学习笔记(16)--Scaffold脚手架、AppBar组件、BottomNavigationBar组件

    如需转载,请注明出处:Flutter学习笔记(15)--MaterialApp应用组件及routes路由详解 今天的内容是Scaffold脚手架.AppBar组件.BottomNavigationBa ...

  3. javaSE学习笔记(16)---网络编程

    javaSE学习笔记(16)---网络编程 基本概念 如今,计算机已经成为人们学习.工作.生活必不可少的工具.我们利用计算机可以和亲朋好友网上聊天,也可以玩网游.发邮件等等,这些功能实现都离不开计算机 ...

  4. java JDK8 学习笔记——第16章 整合数据库

    第十六章 整合数据库 16.1 JDBC入门 16.1.1 JDBC简介 1.JDBC是java联机数据库的标准规范.它定义了一组标准类与接口,标准API中的接口会有数据库厂商操作,称为JDBC驱动程 ...

  5. RocketMQ学习笔记(16)----RocketMQ搭建双主双从(异步复制)集群

    1. 修改RocketMQ默认启动端口 由于只有两台机器,部署双主双从需要四个节点,所以只能修改rocketmq的默认启动端口,从官网下载rocketmq的source文件,解压后使用idea打开,全 ...

  6. 《C#本质论》读书笔记(16)构建自定义集合

    16.1 更多集合接口 集合类(这里指IEnumerable层次结构)实现的接口层次结构 16.1.1 IList<T>与IDictionary<TKey,TValue> 字典 ...

  7. 读CLR via C#笔记

    1.is 和 as 的区别 public class Employee { } a): object obj = new Employee(); if (obj is Employee) { Empl ...

  8. Java菜鸟学习笔记--数组篇(三):二维数组

    定义 //1.二维数组的定义 //2.二维数组的内存空间 //3.不规则数组 package me.array; public class Array2Demo{ public static void ...

  9. php 学习笔记 数组3

    15.使用数组 1).并集(union)  array_merge(array1,array2,array3..) 函数把两个或多个数组合并为一个数组,后面覆盖前面 2). 交集(intersecti ...

  10. java笔记 -- 数组

    概念: 数组是一种数据结构, 用来存储同一类型值的集合. 通过一个整型的下标可以访问数组中的每一个值. 声明: int[] a(推荐,将类型int[](整形数组)和变量名分开了) 或者int a[] ...

随机推荐

  1. ASP.NET Core 将文件夹内容输出为压缩包文件方法

    本文主要是告诉大家一个省内存的方法,将整个文件夹的内容作为一个压缩包输出,但是实际上没有申请那么多的内存,也不需要升级创建一个压缩包文件.原理是通过逐个读文件然后按照压缩包格式输出 在每个请求的方法可 ...

  2. OLAP系列之分析型数据库clickhouse集群部署(二)

    一.环境准备 IP 配置 clickhouse版本 zookeeper版本 myid 192.168.12.88 Centos 7.9 4核8G 22.8.20.11 3.7.1 3 192.168. ...

  3. docker-compose安装EFK

    一.环境 IP 系统 配置 版本 192.168.10.100 Centos7.9 2核4G Docker Compose version v2.19.1.EFK-7.17.11 EFK版本是试用版本 ...

  4. async 与 promise 的区别

    async函数会引式返回一个promise,而promise的resolve值就是函数return的值 使用async和await明显节约了不少代码,不需要.then,不需要写匿名函数处理promis ...

  5. SAP集成技术(四)五种集成架构

    本文中,我们将介绍并解释五个主要的模型.我们主要区分直接集成.中间件导向集成以及两个一般的架构概念.直接集成(例如点对点集成)中的标准化很少,但中间件导向的拓扑(例如中心辐射型拓扑以及企业服务总线)追 ...

  6. IPD、CMMI、敏捷

    华为公司早在2009年正式发文在全公司现在流程IPD.CMMI的基础上,所有产品线的软件开发团队全面推行敏捷开发.除了华为之外,不仅是互联网企业,现在凡是涉及到软件开发的企业对敏捷都不陌生,那么IPD ...

  7. 记录Notion API Authorization中的一个坑

    正文 Notion官方文档的Authorization部分提到: In your integration code, include the token in the Authorization he ...

  8. Ubuntu20.04桌面版图文安装(超详细)

    参考文档: https://baijiahao.baidu.com/s?id=1670100505795119581&wfr=spider&for=pc https://mirrors ...

  9. 源码研习 — TVM中的IR设计与技术实现

    一.关键问题 TVM中的 IR 是什么,架构设计上分几层? 解答:TVM的整体结构图如下: 概念上,分为两层:上层为面向前端组网的Relay IR, 下层为面向LLVM的底层 IR. 但从设计实现上, ...

  10. WEB服务与NGINX(7)-实现自定义错误页面

    1. 自定义错误页面 error_page code ... [=[response]] uri; 定义错误页,以指定的响应状态码进行响应,此指令由ngx_http_index_module模块提供 ...