返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >c#系列 list详情
  • 799
分享到

c#系列 list详情

2024-04-02 19:04:59 799人浏览 八月长安
摘要

目录这里以list为介绍: private static readonly T[] s_emptyArray = new T[0]; public List() { this

这里以list为介绍:


private static readonly T[] s_emptyArray = new T[0];
public List()
{
  this._items = List<T>.s_emptyArray;
}

list 本质是一个数组

同样我们可以指定容量,如果我们知道了我们大概需要多少数据,那么我们可以指定一下,这样避免了resize的损耗。

就跟我们操作系统一样,提前申请内存大小。所以我们程序一般都有一个申请内存,实际使用内存,内存碎片这几个概念。

添加也是很简单哈


public void Add(T item)
{
  ++this._version;
  T[] items = this._items;
  int size = this._size;
  if ((uint) size < (uint) items.Length)
  {
 this._size = size + 1;
 items[size] = item;
  }
  else
 this.AddWithResize(item);
}

判断是否满了,如果没满直接存到数组里面去,如果满了,那么resize一下。

看下resize:


private void AddWithResize(T item)
{
  int size = this._size;
  this.EnsureCapacity(size + 1);
  this._size = size + 1;
  this._items[size] = item;
}


然后看一下扩容步骤:


private void EnsureCapacity(int min)
{
  if (this._items.Length >= min)
 return;
  int num = this._items.Length == 0 ? 4 : this._items.Length * 2;
  if ((uint) num > 2146435071U)
 num = 2146435071;
  if (num < min)
 num = min;
  this.Capacity = num;
}

首先在做了一次判断,判断是否容量够用,所以是size+1


if (this._items.Length >= min)
 return;


这里就有人问了外面不是判断了,为什么里面还有判断。

这个就是一些人喜欢谈性能的地方了,认为多此一举,如果里面不判断那么就不是一个成熟的方法,提现不出方法的封闭性,因为方法的作用是之和参数打交道,外面是什么其实是不管的。

那么可以看出,一开始是4,然后后面就是翻倍了。

然后重点看下:


 this.Capacity = num;


这个this.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;
   }
  }
 }
}

首先判断了不能缩容,如果缩容直接异常,其次我们注意道这个Capacity piblic的,也就是说我们在外部就可以直接调用。

后面逻辑就很简单创建一个新的数组,然后复制就ok了,然后重新赋值_items

那么来看一下remove吧:


public bool Remove(T item)
{
 int index = IndexOf(item);
 if (index >= 0)
 {
  RemoveAt(index);
  return true;
 }

 return false;
}

首先是找到其位置:


public int IndexOf(T item)
 => Array.IndexOf(_items, item, 0, _size);

int IList.IndexOf(object? item)
{
 if (IsCompatibleObject(item))
 {
  return IndexOf((T)item!);
 }
 return -1;
}

可以看一下这个IsCompatibleObject,还是很有趣的。


private static bool IsCompatibleObject(object? value)
{
 // Non-null values are fine.  Only accept nulls if T is a class or Nullable<U>.
 // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
 return (value is T) || (value == null && default(T) == null);
}

从这个说明,其实我们是可以传空对象的。


static void Main(string[] args)
{
 List<object> lists = new List<object>();

 lists.Add(null);

 Console.WriteLine(lists.Count);

 lists.Remove(null);
 Console.ReadLine();
}



 

那么来看一下removeat吧:


public void RemoveAt(int index)
{
 if ((uint)index >= (uint)_size)
 {
  ThrowHelper.ThrowArgumentOutOfRange_IndexException();
 }
 _size--;
 if (index < _size)
 {
  Array.Copy(_items, index + 1, _items, index, _size - index);
 }
 if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
 {
  _items[_size] = default!;
 }
 _version++;
}

这里可以看出list的remove操作还是性能损耗很大的,尤其是大的list

这里有没有注意道一个_version,这个有什么作用呢?

当遍历的时候我们就用的到


internal Enumerator(List<T> list)
{
 _list = list;
 _index = 0;
 _version = list._version;
 _current = default;
}

public void Dispose()
{
}

public bool MoveNext()
{
 List<T> localList = _list;

 if (_version == localList._version && ((uint)_index < (uint)localList._size))
 {
  _current = localList._items[_index];
  _index++;
  return true;
 }
 return MoveNextRare();
}

private bool MoveNextRare()
{
 if (_version != _list._version)
 {
  ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
 }

 _index = _list._size + 1;
 _current = default;
 return false;
}

重点看上面的list,上面表面了,当我们使用foreach 进行遍历的时候,如果我们进行了删除或者添加,那么_version就会发生变化,那么可想而知会抛出异常。

例子:


static void Main(string[] args)
{
 List<object> lists = new List<object>();

 lists.Add("123456");

 lists.Add("1231246");

 lists.Add("dsadadsads");

 lists.Add("eqewqew");

 foreach (var item in lists)
 {
  if (item.ToString() == "1231246")
  {
   lists.Remove(item);
  }
 }

 Console.ReadLine();
}

然后就会抛出异常了。

那么这里就不介绍find了,find 就是遍历数组,找出是否相等。

哦,对了讲另外一个故事。


public int Count => _size;


count-1 就是当前插入的位置。

那么如果你想删除某个元素的时候,那么你可以进行removeat 删除,这样避免了find。

那么非常值得注意的是如果删除了其他元素,如果那么元素的位置小于你记录的位置,那么应该是位置进行减一。

到此这篇关于C#系列 list详情的文章就介绍到这了,更多相关c#系列 list内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: c#系列 list详情

本文链接: https://lsjlt.com/news/155318.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • c#系列 list详情
    目录这里以list为介绍: private static readonly T[] s_emptyArray = new T[0]; public List() { this...
    99+
    2024-04-02
  • python列表[list]和元组(tuple)详情
    列表和元组: list是一种有序的集合,可以随时添加和删除其中的元素.1,创建一个普通列表 List = ['Jack','Bob','Lucy','Rose'] Append() ...
    99+
    2024-04-02
  • Python list列表查找元素详情
    目录Python list列表index() 方法count()方法Python list列表 Python 列表(list)提供了 index() 和 count() 方法,它们都...
    99+
    2024-04-02
  • C语言队列和应用详情
    目录1.队列的原理2.队列的作用3.队列程序设计思路4.入列5.出列6.掌握队列程序编写7.队列的应用1.队列的原理 队列原理其实就像一个管道,如果我们不断往管道里面塞乒乓球,每个乒...
    99+
    2024-04-02
  • python列表详情
    目录1.列表2.使用格式3.一些很有用的函数4.元组 tuple5.元组的常用函数1.列表 python没有数组,而是引入了列表(list),列表可以存储任何类型的数据,而且同一个...
    99+
    2024-04-02
  • Python 列表list详解(超详细)
    文章目录 Python内置函数/方法详解—列表list1、创建列表1.1 使用 [ ] 创建列表1.2 使用 list() 函数 创建(转换为)列表 2、访问列表2.1 下标索引访问2....
    99+
    2023-08-31
    python 开发语言 pycharm 算法 后端
  • MySQL行转列详情
    目录一、行转列SQL写法二、如果领导@你,让你在结果集中加上总数列呢?三、领导又双叒叕@你改需求四、结束语附录:创建表结构&测试数据SQL  MySQL行...
    99+
    2024-04-02
  • Flutter中GetX系列六--GetxController/GetView使用详情
    1.GetxController介绍 在实际的项目开发过程中,我们不可能把UI代码、业务逻辑都放在一起处理,这样对项目的架构、代码的可读性、后期的维护将会是致命的,好在GetX为我们提供了GetxController,GetxControl...
    99+
    2023-10-01
    flutter GetxController 数据更新 事件监听 改变唯一的值 GetView使用详情
  • Python list(列表) 详细总结
    添加List.append('yy')  #追加到末尾 List.insert(0,'yy')  #追加到列首,适用场景是给Python添加环境变量时。 # 如: sys.path.insert(0,path)修改List[0] = 'yl...
    99+
    2023-01-31
    详细 列表 Python
  • Python列表list详解篇(七)
    介绍:列表是最常用的python数据类型,它可以作为一个方括号内的逗号用分隔值出现。列表的数据项不需要具有相同的类型。创建一个列表,只要逗号分隔的不同数据项用方括号括起来即可。name=[‘’beijing,’shenzhen’,’nanj...
    99+
    2023-01-31
    详解 列表 Python
  • SQL行转列与列转行详情
    1.数据集 +---+----------+ |id |login_date| +---+----------+ |01 |2021-02-28| |01 |2021-03-01| ...
    99+
    2024-04-02
  • C++ 轻量级对象JSON序列化实现详情
    目录1、设计思路2、匹配基本类型的Unmarshal模板3、匹配stl容器/其他第三方类库的Unmarshal模板4、匹配自定义struct/class的Unmarshal模板5、测...
    99+
    2024-04-02
  • Redis List列表的详细介绍
    Redis List列表的详细介绍 Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边) 一个列表最多可以包含 232 - 1 个元素 (42949...
    99+
    2022-06-04
    详细介绍 列表 Redis
  • C/C++内存管理详情
    目录C/C++内存管理1. C/C++内存分布2. C语言中动态内存管理方式2.1 malloc/calloc/realloc和free3. C++内存管理方式3.1 new/del...
    99+
    2024-04-02
  • java系列之list集合分组
    文章目录 前言一、list是什么?二、list集合分组总结 前言 在Java编程中,List集合是一种常用的数据结构,用于存储一组元素。有时候,我们需要对List集合中的元素进行分组操作...
    99+
    2023-09-09
    java list
  • C++this指针详情
    还是Stock股票这个类,假设我们要实现一个方法,比较一下当前股票和传入的股票, 返回价格高的那个股票。在我们实现的时候,会遇到一点问题。 const Stock & Sto...
    99+
    2024-04-02
  • Python列表推导式详情
    目录1、列表生成式1.1 案例2、集合生成式3、字典生成式1、列表生成式 列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list...
    99+
    2024-04-02
  • PHP的序列化和反序列化详情
    目录一、PHP 为什么要反序列化?二、PHP如何反序列化?三、PHP反序列化漏洞1、常用 的魔术方法2、漏洞产生条件3、题目一、PHP 为什么要反序列化? PHP程序执行结束以后会将...
    99+
    2024-04-02
  • Python的列表和元组详情
    目录一、Python 列表(list)1.序列介绍2.列表的概述列表是包含0个或者多个元素的有序序列,属于序列类型。3.创建列表4.列表的索引5.列表的分片6.列表的分片赋值7.循环...
    99+
    2024-04-02
  • C#异步原理详情
    目录一、关于第一点的说明二、关于第二点的说明三、关于第三点的说明四、关于第四点的说明五、关于第五点的说明前言: 用async关键字和await表达式表达的异步操作在C#5便发布了,其...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作