C# 中的 数组[]、ArrayList、List
C# 中的 数组[]
、ArrayList
、List
数组
在 C# 中,数组实际上是对象,而不只是如在 C 和 C++ 中的连续内存的可寻址区域。
属性:
- 数组可以是一维、多维或交错的。
- 创建数组实例时,将建立纬度数量和每个纬度的长度。 这些值在实例的生存期内无法更改。
- 数值数组元素的默认值设置为零,而引用元素设置为 null。
- 交错数组是数组的数组,因此其元素为引用类型且被初始化为 null。
- 数组从零开始编制索引:包含 n 元素的数组从 0 索引到 n-1。
- 数组元素可以是任何类型,其中包括数组类型。
- 数组类型是从抽象的基类型
Array
派生的引用类型。 所有数组都会实现IList
和IEnumerable
。 可在 C# 中使用foreach
迭代数组。 原因是单维数组还实现了IList<T>
和IEnumerable<T>
。
命名空间:
System;
特点
内存连续存储;索引速度快;赋值修改元素简单缺点
插入数据麻烦(连续内存,插入后续的元素都需要移动);声明数组需指定长度(长了没用完浪费内存,短了可能不够用);分类
- 单维数组 eg:
int[] array = new int[5];
- 多维数组 eg:
int[,] array = new int[4, 2]; // 四行两列的二维数组
int[,,] array3Da = new int[2, 2, 3] {
{ { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } }
}; // 三个维度(2、2 和 3)的数组
- 交错数组 eg:
// 声明一个具有三个元素的一维数组,其中每个元素都是一维整数数组
int[][] jaggedArray = new int[3][]; // 必须初始化的元素后才可使用它
jaggedArray[0] = new int[5];
jaggedArray[1] = new int[4];
jaggedArray[2] = new int[2];
- 隐式类型的数组
通常用于查询表达式、匿名类型、对象和集合初始值设定项.
var a = new[] { 1, 10, 100, 1000 }; // int[]
var b = new[] { "hello", null, "world" }; // string[]
- 单维数组 eg:
Array
数组类型([]
)是从抽象的基类型 Array
派生的引用类型。
Array
类提供一些方法,用于创建、处理、搜索数组并对数组进行排序,从而充当公共语言运行时中所有数组的基类。
Array
的用法与数组[]
几乎一样,可以看做是数组。在定义的时候需要指定长度。
Array
的 公共静态成员(public static
)是线程安全的。但不保证所有实例成员都是线程安全的。
Array.SyncRoot
属性,用于同步对 Array
的访问的对象。
下面的代码示例演示如何使用属性在整个枚举过程中锁定数组 SyncRoot
Array myArray = new int[] { 1, 2, 4 };
lock(myArray.SyncRoot)
{
foreach (Object item in myArray)
Console.WriteLine(item);
}
ArrayList
为了解决数组的一些短板,ArrayList
继承了 IList
接口,提供了数据存储和检索。 ArrayList
对象的大小是按照其中存储的数据来动态扩充与收缩的。在声明 ArrayList
对象时并不需要指定它的长度。
- 命名空间:
System.Collections;
- 特点
允许插入不同类型的数据(插入object
),无需指定长度;只有一个维度 - 缺点
处理数据可能会报类型不匹配的错误;在存储或检索值类型时通常发生装箱和取消装箱操作,性能耗损较大
装箱:就是将值类型的数据打包到引用类型的实例中
拆箱:就是从引用数据中提取值类型
一些方法:
public virtual int Add(object? value);
:将对象添加到 ArrayList
的结尾处,返回已添加 value
的 ArrayList
索引
public virtual void Remove (object? obj);
:从 ArrayList
中移除特定对象的第一个匹配项
ArrayList 是使用 object 数组 实现的,它涉及拆箱和装箱。默认容量 4
public class ArrayList : IList, ICloneable
{
private object?[] _items; // Do not rename (binary serialization)
private int _size; // Do not rename (binary serialization)
private int _version; // Do not rename (binary serialization)
private const int _defaultCapacity = 4;
// Constructs a ArrayList. The list is initially empty and has a capacity
// of zero. Upon adding the first element to the list the capacity is
// increased to _defaultCapacity, and then increased in multiples of two as required.
public ArrayList()
{
_items = Array.Empty<object>();
}
// Constructs a ArrayList with a given initial capacity. The list is
// initially empty, but will have room for the given number of elements
// before any reallocations are required.
//
public ArrayList(int capacity)
{
if (capacity < 0) throw new ArgumentOutOfRangeException(nameof(capacity), SR.Format(SR.ArgumentOutOfRange_MustBeNonNegNum, nameof(capacity)));
if (capacity == 0)
_items = Array.Empty<object>();
else
_items = new object[capacity];
}
}
扩容:
ArrayList 在内部有一个存放数据的数组,当新增数据时候,如果该数组有可用,则会将数据放入数组,并将下标向后移动,如果没有足够的数组,则会进行扩容,如果创建的时候没有给定容量,第一次扩容则会使用默认的容量,如果当前有元素,则会扩容至当前容量的两倍。
可以看到扩容 是将原数组的数据拷贝到新创建的数组中
// Adds the given object to the end of this list. The size of the list is
// increased by one. If required, the capacity of the list is doubled
// before adding the new element.
public virtual int Add(object? value)
{
if (_size == _items.Length) EnsureCapacity(_size + 1);
_items[_size] = value;
_version++;
return _size++;
}
// Ensures that the capacity of this list is at least the given minimum
// value. If the current capacity of the list is less than min, the
// capacity is increased to twice the current capacity or to min,
// whichever is larger.
private void EnsureCapacity(int min)
{
if (_items.Length < min)
{
int newCapacity = _items.Length == 0 ? _defaultCapacity : _items.Length * 2;
// Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
if ((uint)newCapacity > Array.MaxLength) newCapacity = Array.MaxLength;
if (newCapacity < min) newCapacity = min;
Capacity = newCapacity;
}
}
// Gets and sets the capacity of this list. The capacity is the size of
// the internal array used to hold items. When set, the internal
// array of the list is reallocated to the given capacity.
public virtual int Capacity
{
get => _items.Length;
set
{
if (value < _size)
{
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_SmallCapacity);
}
// We don't want to update the version number when we change the capacity.
// Some existing applications have dependency on this.
if (value != _items.Length)
{
if (value > 0)
{
object[] newItems = new object[value];
if (_size > 0)
{
Array.Copy(_items, newItems, _size);
}
_items = newItems;
}
else
{
_items = new object[_defaultCapacity];
}
}
}
}
List
通过使用大小根据需要动态增加的数组来实现泛型接口。
相比于ArrayList
,List<T>
不存在装箱拆箱的缺点,List
类是ArrayList
类的泛型等效类,它的大部分用法都与ArrayList
相似,因为List
类也继承了IList
接口。最关键的区别在于,在声明List
集合时,需要为其声明List
集合内数据的对象类型。
- 命名空间
System.Collections.Generic
- 特点
插入类型固定(泛型);无需指定长度,只有一个维度,允许重复元素
List底层实现使用 泛型数组(Array),默认容量 4,初始化时候可以指定初始化容量,如果不指定则会给定一个空的泛型数组。
public class List<T>:IList<T>,IList,IReadOnlyList<T>
{
private const int DefaultCapacity = 4;
internal T[] _items;
internal int _size;
private int _version;
public List()
{
_items = s_emptyArray;
}
public List(int capacity)
{
if (capacity < 0)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
if (capacity == 0)
_items = s_emptyArray;
else
_items = new T[capacity];
}
}
扩容: List 在内部有一个存放数据的数组,当新增数据时候,如果该数组有可用,则会将数据放入数组,并将下标向后移动,如果没有足够的数组,则会进行扩容,如果创建的时候没有给定容量,第一次扩容则会使用默认的容量,如果当前有元素,则会扩容至当前容量的两倍。
可以看到扩容 是将原数组的数据拷贝到新创建的数组中
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(T item)
{
_version++;
T[] array = _items;
int size = _size;
if ((uint)size < (uint)array.Length)
{
_size = size + 1;
array[size] = item;
}
else
{
AddWithResize(item);
}
}
// Non-inline from List.Add to improve its code quality as uncommon path
[MethodImpl(MethodImplOptions.NoInlining)]
private void AddWithResize(T item)
{
Debug.Assert(_size == _items.Length);
int size = _size;
Grow(size + 1); // 扩容
_size = size + 1;
_items[size] = item;
}
private void Grow(int capacity)
{
Debug.Assert(_items.Length < capacity);
int newcapacity = _items.Length == 0 ? DefaultCapacity : 2 * _items.Length;
// Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
if ((uint)newcapacity > Array.MaxLength) newcapacity = Array.MaxLength;
// If the computed capacity is still less than specified, set to the original argument.
// Capacities exceeding Array.MaxLength will be surfaced as OutOfMemoryException by Array.Resize.
if (newcapacity < capacity) newcapacity = capacity;
Capacity = newcapacity;
}
// Gets and sets the capacity of this list. The capacity is the size of
// the internal array used to hold items. When set, the internal
// array of the list is reallocated to the given capacity.
public int Capacity
{
get => _items.Length;
set
{
if (value < _size)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
}
if (value != _items.Length)
{
if (value > 0)
{
T[] newItems = new T[value];
if (_size > 0)
{
Array.Copy(_items, newItems, _size);
}
_items = newItems;
}
else
{
_items = s_emptyArray;
}
}
}
}
C# 中的 数组[]、ArrayList、List的更多相关文章
- c#中的数组、ArrayList、List区别【转】
首先说明C#中的Array类:Array 类是 C# 中所有数组的基类,它是在 System 命名空间中定义.Array 类提供了各种用于数组的属性和方法.关于Array类的一些属性及方法详见博文:C ...
- c#中的数组、ArrayList、List区别
首先说明C#中的Array类:Array 类是 C# 中所有数组的基类,它是在 System 命名空间中定义.Array 类提供了各种用于数组的属性和方法.关于Array类的一些属性及方法详见博文:C ...
- java 在循环中删除数组元素
在写代码中经常会遇到需要在数组循环中删除数组元素的情况,但删除会导致数组长度变化. package com.fortunedr.thirdReport; import java.util.ArrayL ...
- Java中List,ArrayList、Vector,map,HashTable,HashMap区别用法
Java中List,ArrayList.Vector,map,HashTable,HashMap区别用法 标签: vectorhashmaplistjavaiteratorinteger ArrayL ...
- go语言中的数组切片:特立独行的可变数组
go语言中的数组切片:特立独行的可变数组 初看go语言中的slice,觉得是可变数组的一种很不错的实现,直接在语言语法的层面支持,操作方面比起java中的ArrayList方便了许多.但是在使用了一段 ...
- 浅谈JAVA中HashMap、ArrayList、StringBuilder等的扩容机制
JAVA中的部分需要扩容的内容总结如下:第一部分: HashMap<String, String> hmap=new HashMap<>(); HashSet<Strin ...
- Java中的数组与集合
此文转载自:http://student-lp.iteye.com/blog/2082362 在java编程的过程中,我们不能确定某一类型的对象到底会需要多少,为了解决这个问题,java提供了容纳对象 ...
- Java 中 Vector、ArrayList、List 使用深入剖析
线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构.这些类均在java.util包中.本文试图通过简单的描述,向读者阐述各个类的作用以 ...
- C#基础-数组-ArrayList
数组ArrayList using System.Collections; //表示引入集合的命名空间 数组ArrayList容量本身是不固定的,根据存储的数据动态变化 // 声明一个ArrayLis ...
- java中一个数组不能放不同数据类型的值
在java中,数组不能放不同数据类型的值. 方法一: 多态 定义数组类型的时候定义为父类,而存进数组为父类的子类 public class test2 { public static void mai ...
随机推荐
- pytest常用断言
如上官网所说,pytest使用python中的assert来比较实际值与预期值,实现断言功能 1 常用的断言方式 assert xxx assert a == b assert a!=b assert ...
- 【Redis】Cluster集群
一.Redis Cluster 工作原理 在引入哨兵机制后,解决了Redis主从架构Master故障时的主从切换问题,保证了Redis服务可用性.但依旧无法解决单机节点出现的写入性能瓶颈(网卡速率.单 ...
- selenium控制文件下载位置
selenium控制文件下载位置 我们在自动化下载文件的时候势必存在一种需求: 通过chrome将文件保存到指定位置 1. google窗口实现 配置'prefs'将文件下载到指定位置, 并通过判 ...
- 跑在笔记本里的大语言模型 - GPT4All
何为GPT4All GPT4All 官网给自己的定义是:一款免费使用.本地运行.隐私感知的聊天机器人,无需GPU或互联网. 从官网可以得知其主要特点是: 本地运行(可包装成自主知识产权) 无需GPU( ...
- 2021-06-22:现有司机N*2人,调度中心会将所有司机平分给A、B两个区域,第 i 个司机去A可得收入为income[i][0],第 i 个司机去B可得收入为income[i][1],返回所有调
2021-06-22:现有司机N*2人,调度中心会将所有司机平分给A.B两个区域,第 i 个司机去A可得收入为income[i][0],第 i 个司机去B可得收入为income[i][1],返回所有调 ...
- 一次redis主从切换导致的数据丢失与陷入只读状态故障
背景 最近一组业务redis数据不断增长需要扩容内存,而扩容内存则需要重启云主机,在按计划扩容升级执行主从切换时意外发生了数据丢失与master进入只读状态的故障,这里记录分享一下. 业务redis高 ...
- 计算机网络 vlan
目录 一.vlan的概念 二.vlan的优势 三.vlan的种类 四.静态vlan的配置 五.trunk的概念和配值 六.实验 一.vlan的概念 在传统的以太网中,所有的用户都是同一个广播域,当数据 ...
- 从源码角度剖析 golang 如何fork一个进程
从源码角度剖析 golang 如何fork一个进程 创建一个新进程分为两个步骤,一个是fork系统调用,一个是execve 系统调用,fork调用会复用父进程的堆栈,而execve直接覆盖当前进程的堆 ...
- linux 递归和函数实验
递归 作用:自己调用自己 1.例子:阶乘 2.遍历目录下所有文件 函数 1.函数能够接受一个参数,参数为用户名: 判断一个用户是否存在 如果存在,就返回此用户的shell 和 UID :并返回正常状态 ...
- Ascend C sqrt算子实战
摘要:编写一个Ascend C的sqrt算子,并通过内核调用方式在cpu和npu模式下进行验证. 本文分享自华为云社区<[2023 · CANN训练营第一季]--Ascend C sqrt算子实 ...