【从零开始入门unity游戏开发之——C#篇30】C#常用泛型数据结构类——list<T>列表、`List<T>` 和数组 (`T[]`) 的选择

文章目录

  • 一、常用泛型数据结构类------`list<T>`列表
    • [1、`List` 的本质](#1、List 的本质)
    • [2、声明 `List`](#2、声明 List)
    • 3、增删查改操作
      • [增(Add, AddRange, Insert)](#增(Add, AddRange, Insert))
      • [删(Remove, RemoveAt, Clear)](#删(Remove, RemoveAt, Clear))
      • [查(索引访问, Contains, IndexOf, LastIndexOf)](#查(索引访问, Contains, IndexOf, LastIndexOf))
      • 改(修改元素)
    • [4、遍历 `List`](#4、遍历 List)
      • [使用 `for` 循环遍历:](#使用 for 循环遍历:)
      • [使用 `foreach` 循环遍历:](#使用 foreach 循环遍历:)
    • 5、性能优化与注意事项
    • 6、总结
  • [二、`List<T>` 和数组 (`T[]`) 的选择](#二、List<T> 和数组 (T[]) 的选择)
    • [1、**使用数组 (`T[]`) 的情况**](#1、使用数组 (T[]) 的情况)
      • [a. **已知大小且不需要动态改变长度**](#a. 已知大小且不需要动态改变长度)
      • [b. **性能要求高**](#b. 性能要求高)
      • [c. **没有频繁的插入和删除操作**](#c. 没有频繁的插入和删除操作)
    • [2、**使用 List<T> 的情况**](#2、使用 List<T> 的情况)
      • [a. **集合大小不确定或动态变化**](#a. 集合大小不确定或动态变化)
      • [b. **需要使用 `Add`, `Insert`, `Remove` 等方法**](#b. 需要使用 Add, Insert, Remove 等方法)
      • [c. **需要更丰富的 API 支持**](#c. 需要更丰富的 API 支持)
    • 3、**性能和内存管理的差异**
    • 总结:
  • 专栏推荐
  • 完结

一、常用泛型数据结构类------list<T>列表

你的C# List 知识点整理得很不错,但有一些小错误和格式问题需要修复。下面是一个更清晰、规范和优化的版本,并做了一些补充:

1、List 的本质

List 是 C# 中的一个泛型集合类,它本质上是一个可以动态扩展的数组,支持自动扩展容量。它封装了对数组的增删查改等操作,使得开发人员可以更加方便地操作集合数据。

List<T> 在某种程度上确实可以被看作是一个泛型版本的 ArrayList。现代 C# 开发推荐使用 List<T>,而避免使用 ArrayList

2、声明 List

声明 List 时,需要引用 System.Collections.Generic 命名空间。

csharp 复制代码
// 引入命名空间
using System.Collections.Generic;

// 声明 List 实例
List<int> list = new List<int>();       // 整型 List
List<string> list2 = new List<string>(); // 字符串型 List
List<bool> list3 = new List<bool>();    // 布尔型 List

3、增删查改操作

增(Add, AddRange, Insert)

  • Add():在列表末尾添加一个元素。
  • AddRange():添加一个集合到当前列表的末尾。
  • Insert():在指定位置插入一个元素。
csharp 复制代码
// 增加元素
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);

// 添加集合
List<string> listStr = new List<string>();
listStr.Add("123");
list2.AddRange(listStr);

// 在指定位置插入元素
list.Insert(0, 999);  // 在位置0插入999

// 查看添加后的第一个元素
Console.WriteLine(list[0]);  // 输出 999

删(Remove, RemoveAt, Clear)

  • Remove():移除指定元素。
  • RemoveAt():移除指定位置的元素。
  • Clear():移除所有元素。
csharp 复制代码
// 移除指定元素
list.Remove(1); // 移除第一个出现的1

// 移除指定位置的元素
list.RemoveAt(0); // 移除位置0的元素

// 清空列表
list.Clear(); // 移除所有元素

查(索引访问, Contains, IndexOf, LastIndexOf)

  • 使用 [] 操作符直接访问指定位置的元素。
  • Contains():判断列表中是否包含某个元素。
  • IndexOf():从前往后查找元素的索引位置。
  • LastIndexOf():从后往前查找元素的索引位置。
csharp 复制代码
// 访问指定位置的元素
Console.WriteLine(list[0]);  // 输出第一个元素

// 查看元素是否存在
if (list.Contains(1))
{
    Console.WriteLine("存在元素 1");
}

// 查找元素位置
int index = list.IndexOf(5);  // 从前往后查找元素5的位置
Console.WriteLine(index);  // 输出找到的索引,找不到返回 -1

// 反向查找元素位置
index = list.LastIndexOf(2); // 从后往前查找元素2的位置
Console.WriteLine(index);  // 输出找到的索引,找不到返回 -1

改(修改元素)

  • 使用 [] 操作符修改指定位置的元素。
csharp 复制代码
// 修改元素
Console.WriteLine(list[0]);  // 输出修改前的元素
list[0] = 99;                // 修改第一个元素为 99
Console.WriteLine(list[0]);  // 输出修改后的元素

4、遍历 List

  • Count:获取列表中元素的数量。
  • Capacity:获取列表的容量(即列表当前分配的内存大小,通常比实际元素数大以避免频繁扩展)。

使用 for 循环遍历:

csharp 复制代码
// 输出列表的长度和容量
Console.WriteLine("Count: " + list.Count);
Console.WriteLine("Capacity: " + list.Capacity);

// 使用 for 循环遍历
Console.WriteLine("********************");
for (int i = 0; i < list.Count; i++)
{
    Console.WriteLine(list[i]);
}

使用 foreach 循环遍历:

csharp 复制代码
// 使用 foreach 遍历
foreach (int item in list)
{
    Console.WriteLine(item);
}

5、性能优化与注意事项

  1. 扩容机制

    • List 会根据需要自动扩容。当列表的容量不足时,List 会增加其容量,通常是原来容量的 1.5 到 2 倍。通过提前指定 Capacity 来避免频繁的扩容操作,可以提高性能。
  2. 避免不必要的 Insert 操作

    • Insert 操作会将插入位置后的所有元素向后移动,因此性能较低。如果频繁插入大量元素,可以考虑使用 LinkedList(下面会介绍),它在插入操作上有更好的性能。
  3. 内存管理

    • ListClear 操作只是将元素移除,并没有释放内存。如果希望释放内存,可以通过调整 Capacity 来控制。

6、总结

C# 的 List 是一个非常强大且灵活的数据结构,支持动态大小和高效的元素增删改查操作。通过合理使用 AddAddRangeInsertRemove 等方法,可以高效管理集合数据。需要注意性能优化和内存管理,尤其是在处理大量数据时。


二、List<T> 和数组 (T[]) 的选择

1、使用数组 (T[]) 的情况

数组是静态的、大小固定的数据结构。它在以下情况下比较适用:

a. 已知大小且不需要动态改变长度

如果你知道数据集合的大小,并且这个大小在运行过程中不会发生变化,使用数组是一个很好的选择。数组的内存分配是一次性的,不会有后续的内存扩展或收缩。

  • 例子:例如在游戏中存储一个固定数量的敌人或道具,可以使用数组,因为这些元素的数量通常是固定的。
csharp 复制代码
int[] scores = new int[10];  // 存储 10 个固定大小的分数

b. 性能要求高

数组在性能方面通常比 List<T> 更快,因为它不需要额外的封装或扩展机制。数组访问元素的速度非常快,尤其是在对元素进行大量访问时。它的内存分配方式也更为简单。

  • 例子:在某些高性能场景下,比如游戏中的物理模拟、渲染顶点数据时,数组的访问速度和内存使用更加高效。
csharp 复制代码
float[] vertexPositions = new float[1000];  // 存储顶点数据

c. 没有频繁的插入和删除操作

数组一旦创建,大小是固定的,插入或删除元素的操作非常不便,尤其是在数组中间进行插入或删除时,可能涉及到大量的数据移动。因此,如果你的数据不需要频繁变动,数组是一个更好的选择。

2、使用 List 的情况

List<T> 是动态大小的、功能丰富的泛型集合,它适用于以下几种情况:

a. 集合大小不确定或动态变化

如果你无法预先确定集合的大小,或者在运行时会不断地增加或删除元素,List<T> 是更好的选择。List<T> 会根据需要自动扩展大小。

  • 例子:例如在游戏中,玩家可以拾取道具,或敌人会不断生成/消失,数量是动态变化的。
csharp 复制代码
List<Enemy> enemies = new List<Enemy>();  // 动态存储敌人
enemies.Add(new Enemy());                  // 添加新敌人

b. 需要使用 Add, Insert, Remove 等方法

List<T> 提供了比数组更多的灵活性和功能。你可以随时添加、插入或删除元素,且不需要担心元素移动和数组扩展的复杂性。

  • 例子:例如在游戏的某个系统中,你可能需要频繁地向一个列表中添加新的玩家对象或移除不再活跃的玩家。
csharp 复制代码
List<Player> players = new List<Player>();
players.Add(new Player());
players.Remove(playerToRemove);  // 删除指定玩家

c. 需要更丰富的 API 支持

List<T> 提供了许多内置的便利方法,比如 Sort(), Find(), FindAll(), Contains(), Insert(), RemoveAt() 等,可以让你更轻松地操作数据。

  • 例子 :你可以使用 Find 方法快速查找符合条件的元素,或者使用 Sort 对数据进行排序。
csharp 复制代码
List<int> scores = new List<int> { 100, 90, 80 };
scores.Sort();  // 排序
int highestScore = scores.Find(x => x > 90);  // 查找大于 90 的分数

3、性能和内存管理的差异

  • 数组:由于大小固定,它们在内存中的分配是连续的,并且不会有额外的内存分配或移动。因此,它在内存使用方面更加高效。
  • ListList<T> 使用动态数组来存储元素,因此在添加元素时会有额外的内存管理开销。每当 List 的容量不足时,它会进行扩容,通常会翻倍,这会导致内存的浪费。不过,List<T> 在操作上非常灵活,适合处理动态变化的集合。

总结:

  • 使用数组 (T[])

    • 当数据量固定且不需要动态增删时。
    • 需要较高的性能,尤其是大量访问或计算时。
    • 不需要经常修改集合的大小。
  • 使用 List<T>

    • 当集合大小不确定,需要频繁增删元素时。
    • 需要使用一些内置的集合操作(如排序、查找、插入等)。
    • 需要动态变化的集合,而不需要提前知道其大小。

在开发中,如果你面临的是一个会频繁变动(增、删、查)的数据集合,List<T> 是更好的选择。如果你的数据集合在运行时不需要改变,或者需要最高的性能,数组可能更合适。


专栏推荐

地址
【从零开始入门unity游戏开发之------C#篇】
【从零开始入门unity游戏开发之------unity篇】
【制作100个Unity游戏】
【推荐100个unity插件】
【实现100个unity特效】
【unity框架开发】

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!如果你遇到任何问题,也欢迎你评论私信或者加群找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~

相关推荐
mghio6 小时前
Dubbo 中的集群容错
java·微服务·dubbo
咖啡教室11 小时前
java日常开发笔记和开发问题记录
java
咖啡教室11 小时前
java练习项目记录笔记
java
鱼樱前端12 小时前
maven的基础安装和使用--mac/window版本
java·后端
RainbowSea12 小时前
6. RabbitMQ 死信队列的详细操作编写
java·消息队列·rabbitmq
RainbowSea12 小时前
5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
java·消息队列·rabbitmq
我不会编程55514 小时前
Python Cookbook-5.1 对字典排序
开发语言·数据结构·python
李少兄14 小时前
Unirest:优雅的Java HTTP客户端库
java·开发语言·http
此木|西贝14 小时前
【设计模式】原型模式
java·设计模式·原型模式