C# 泛型集合类List<T>使用总结

目录
  • 为什么选择使用List,而不是使用Array,或者ArryList
  • 去重、交集、并集、差集操作
  • 重写Equals() 和 GetHashCode()
  • 简单使用

C#中List可谓是使用最广泛的一种数据类型了,使用他来规范数据时,往往会涉及到对数据的处理操作,相关处理数据方法也非常丰富,本文将简单介绍为何使用它,以及部分处理方法的灵活使用。

为什么选择使用List,而不是使用Array,或者ArryList

首先要说下数组的局限性

(1) 数组中元素是固定的:类型和数量都必须确定!一旦定义,无法改变其元素总数
(2) 如果使用数组类型存储数据,一旦项目需求有变化,那必须修改原数组相关代码,得不偿失
(3) 如果数据总数非常大,那数组在定义时就要把长度(即元素总数)定义的非常大,造成了存储空间的巨大浪费!

而List跟数组比较,他可以动态增减元素个数,无任何限制,直接秒杀数组

当然,实际项目开发中,对于一些固定的枚举值,类型集合等,或相关数据处理中,使用数组还是相当方便的,它并不是没用的,而是相比较List,使用的空间小一些罢了(存在即有用!)

然后再说下ArryList

这个直接截图一下官网的相关建议

既然官网都不建议使用,那可见它真的不常用,而不是不能用
没有使用价值的东西不会被留下来的,对吧!

跟List比较,他还是有一个优点的,就是他可以存储类型不一样的对象数据,而List泛型集合类,其中T必须是对他存储元素对象的约束,必须一致性!

ArrayList存储的对象如果是值类型,那就涉及到装箱操作,这个对程序性能影响很大,所以不到万不得已,还是不要用!

而且ArrayList里面存放元素对象类型都不一致,在C#(强类型语言)中处理时,还需要判断,还要涉及到频繁装箱拆箱,性能不说,这不是自讨苦吃嘛....

其实就跟强类型语言和弱类型语言一样,如果把js比作弱类型,那ts就是强类型,js写起来很爽(var声明变量时,变量几乎可以是任意类型...),但是出现报错、异常,找起来会相当麻烦,因为写的时候,约束的少,那最后运行的时候,都会补回来的!而ts有类型约束以后,写起来有了一些束手束脚,但是基本不会出错,而且写多了都一样!这就是大部分后端语言都是强类型的一个重要原因吧(个人观点....)!

List特点:只能添加一种数据类型,可以是基本的值类型也可以实引用类型,一旦数据类型确定,不可更改!

List做数据处理时,完全可以采用强大的Linq,处理起来那是相当的方便\

去重、交集、并集、差集操作

注:这里仅介绍当List中T为引用类型(对象)时,基本类型(值类型)就不说了,因为可以直接用!....引用类型则不行!

另外还一个类型比较特殊,也要单独拿出来提一嘴,就是string,在C#中它属于引用类型,但是它类似于值类型,可以直接进行比较,在这完全可以归属到值类型当中了。

当然使用Linq中GoupBy + Select等方法还是可以做到去重的,但是这里说的并不是这些东西,而是直接使用IntersectExceptDistinctUnion

那么为什么引用类型不能直接比较呢,其实稍微懂一点底层的都知道,引用类型,引用两个字就道出了缘由!其值为一个引用地址,在栈内存中,地址是唯一的,但是也有可能两个地址指向同一个堆中的值呢....
因此要想比较,先把他的值点出来比较,可以只比较某一个值,也可以是全部

重写Equals() 和 GetHashCode()

为什么要重新呢,因为这些比较方法的内部就是调用者两个方法进行比较的,他们仅适用于值类型的比较,对象需要重写内部逻辑了!

要想重写,需要写一个类,继承IEqualityComparer接口即可

public class MyComparer : IEqualityComparer<Person>
{
    public bool Equals([AllowNull] Person x, [AllowNull] Person y)
    {
        return x.name == y.name && x.age == y.age;
    }

    public int GetHashCode([DisallowNull] Person obj)
    {
        return obj.name.GetHashCode() + obj.age.GetHashCode();
        //return obj.name.GetHashCode() ^ obj.age.GetHashCode();// 两种写法都可以
    }
}

其实上面写法还是有点不严谨
(1)没有null判断,如果某一属性值为空,那就可能抛异常
(2)并未将对象的所有属性进行比较,如上面,仅仅比较名称和年龄,那全国20岁叫张三的人肯定不止一个,达不到目的了(这里仅仅是举个例子,具体比较多少属性,还是根据项目中实际情况而定的...如果有Id,那完全可以比较Id不是更快....)

把(1)加进去重新写一遍

public class MyComparer : IEqualityComparer<Person>
{
    public bool Equals([AllowNull] Person x, [AllowNull] Person y)
    {
        if(x == null || y == null) return false;
        if(x.name == y.name && x.age == y.age) return true;
        return false;
    }

    public int GetHashCode([DisallowNull] Person obj)
    {
        if(obj == null) return 0;
        return obj.name.GetHashCode() + obj.age.GetHashCode();
        //return obj.name.GetHashCode() ^ obj.age.GetHashCode();// 两种写法都可以
    }
}

简单使用

  • 交集
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //交集:集合A.Intersect(集合B)
            var _old = new List<Person> {
                new Person{name="zs",age=21},
                new Person{name="ls",age=10},
                new Person{name="ww",age=13},
                new Person{name="ls",age=10},
                new Person{name="ww",age=13}
            };
            var _new = new List<Person> {
                new Person{name="zs",age=21},
                new Person{name="ls",age=31},
                new Person{name="ww3",age=13}
            };
            var _obj = _old.Intersect(_new,new MyComparer()).ToList();
            for (int i = 0; i < _obj.Count; i++)
            {
                var x = _obj[i];
                Console.WriteLine("name:{0},age:{1}", x.name, x.age);
                //结果: name:zs,age:21
            }
            Console.ReadLine();
        }
    }
    public class Person
    {
        public string name { get; set; }
        public int age { get; set; }
    }
}
  • 差集
var _oj2 = _old.Except(_new, new MyComparer()).ToList();

//结果:
name:ls,age:10
name:ww,age:13
  • 并集
var _oj2 = _old.Union(_new, new MyComparer()).ToList();

//结果:
name:zs,age:21
name:ls,age:10
name:ww,age:13
name:ls,age:31
name:ww3,age:13
  • 去重
var _oj2 = _old.Distinct(new MyComparer()).ToList();

//结果:
name:zs,age:21
name:ls,age:10
name:ww,age:13

到此这篇关于C# 泛型集合类List<T>使用总结的文章就介绍到这了,更多相关C# 泛型List<T>内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C# List<T>的用法小结

    所属命名空间:System.Collections.Generic     public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable List<T>类是 ArrayList 类的泛型等效类.该类使用大小可按需动态增加的数组实现 IList<T> 泛型接口. 泛型的好处: 它为使用c#语言编写面向对象程

  • C#中泛型举例List<T>与DataTable相互转换

    一. DataTable转换到List<T> /// <summary> /// TableToList /// </summary> public class TableListConverter<T> where T : class, new() { public static IList<T> TableToList(DataTable dt) { IList<T> ts = new List<T>();// 定义集

  • C# 如何实现一个带通知的List<T>

    背景 在很多场景下面我们需要在集合发生变化的时候能够通过一个事件对外进行通知,默认的List<T>并没有此类功能,所以对于这一类需求的业务场景下我们需要自己进行相关的扩展,这样才能够符合我们这一需求,这里我来列举一个在项目中经常用到的一个扩展类,在后面我们会对这个进行具体的分析和使用到的C#知识点进行关注. 实现 这里贴出具体的代码实现 using System; using System.Collections.Generic; using System.Linq; namespace XX

  • 关于C#泛型列表List<T>的基本用法总结

    示例代码如下:namespace SampleListT{  class Program  {      static void Main(string[] args)      {//using System.Collections.Generic; 命名空间中的List<T>//using System.Collections; 命名空间中的ArrayList  //都实现了列表集合,一个是泛形集合,一个是非泛型的//下面我们将Person对象加到集合中 Person p1 = new P

  • C#中IList<T>与List<T>的区别深入解析

    写代码时对:IList IList11 =new List ();List List11 =new List (); 有所疑惑,于是在网上搜索一下,很受启发,于是收藏下来,但对部分观点不敢苟同,用红色字体标明我的看法! 首先IList 泛型接口是 ICollection 泛型接口的子代,并且是所有泛型列表的基接口.它仅仅是所有泛型类型的接口,并没有太多方法可以方便实用,如果仅仅是作为集合数据的承载体,确实,IList可以胜任.不过,更多的时候,我们要对集合数据进行处理,从中筛选数据或者排序.这个

  • C#列表List<T>、HashSet和只读集合介绍

    目录 一.概述 二.声明及初始化 三.常用属性和方法 1.添加元素 2.删除元素 3.访问列表元素以及遍历列表: 4.判断元素存在: 5.搜索: 6.排序: 7.转换: 8.去掉重复项(Distinct) 9.只读集合 四:HashSet<T> 1.常用方法 2.HashSet和SortedSet的区别 五.链表 LinkedList 1.链表的内存表视图 2.实例: 一.概述 List<T> 是ArrayList类的等效泛型类.属System.Collections.Generi

  • 浅谈C#中List<T>对象的深度拷贝问题

    一.List<T>对象中的T是值类型的情况(int 类型等) 对于值类型的List直接用以下方法就可以复制: List<T> oldList = new List<T>(); oldList.Add(..); List<T> newList = new List<T>(oldList); 二.List<T>对象中的T是引用类型的情况(例如自定义的实体类) 1.对于引用类型的List无法用以上方法进行复制,只会复制List中对象的引用,

  • C# List<T> Contains<T>()的用法小结

    泛型List<T>中有一个比较列表是否已包含对象的方法Contains<T>(),今天在网上搜了一个用法,记录下来,备查. 要用此方法比较我们的自定义对象,首先要有一个比较器, 要注意的是,这里的比较器是实现IEqualityComparer<T>接口的,不要写成IComparer<T>. 如下: 复制代码 代码如下: /// <summary>    /// 描    述:弹出模型对象列表比较器(根据ID比较)    /// </summ

  • C# 泛型集合类List<T>使用总结

    目录 为什么选择使用List,而不是使用Array,或者ArryList 去重.交集.并集.差集操作 重写Equals() 和 GetHashCode() 简单使用 C#中List可谓是使用最广泛的一种数据类型了,使用他来规范数据时,往往会涉及到对数据的处理操作,相关处理数据方法也非常丰富,本文将简单介绍为何使用它,以及部分处理方法的灵活使用. 为什么选择使用List,而不是使用Array,或者ArryList 首先要说下数组的局限性 (1) 数组中元素是固定的:类型和数量都必须确定!一旦定义,

  • C#泛型集合类System.Collections.Generic

    目录 一.定义泛型类 二.从泛型类继承 三.定义泛型运算符 四.定义泛型结构 五.定义泛型接口 六.定义泛型方法 1.普通类 2.泛型类 七.定义泛型委托 1.通过泛型委托,委托的参数可以在以后定义. 2.常用内置委托: 3.实例: 八.定义泛型事件 九.可空类型System.Nullable<T> 1.声明和赋值 2.判断为空 3.转换 十.ArraySegement<T> 数组片段 一.定义泛型类 void Main() { //实例化泛型类时,才指定具体的类型 MyGener

  • C#泛型Dictionary的用法实例详解

    本文以实例形式讲述了C#中的泛型Dictionary的用法.具有很好的实用价值.分享给大家供大家参考.具体如下: 泛型最常见的用途是泛型集合,命名空间System.Collections.Generic 中包含了一些基于泛型的集合类,使用泛型集合类可以提供更高的类型安全性,还有更高的性能,避免了非泛型集合的重复的装箱和拆箱. 很多非泛型集合类都有对应的泛型集合类,下面是常用的非泛型集合类以及对应的泛型集合类: 非泛型集合类 泛型集合类 ArrayList List<T> HashTable D

  • 详解C#中的泛型以及编程中使用泛型的优点

    2.0 版 C# 语言和公共语言运行时 (CLR) 中增加了泛型.泛型将类型参数的概念引入 .NET Framework,类型参数使得设计如下类和方法成为可能:这些类和方法将一个或多个类型的指定推迟到客户端代码声明并实例化该类或方法的时候.例如,通过使用泛型类型参数 T,您可以编写其他客户端代码能够使用的单个类,而不致引入运行时强制转换或装箱操作的成本或风险,如下所示: // Declare the generic class. public class GenericList<T> { vo

  • 深入理解java泛型详解

    什么是泛型? 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样. 可以在集合框架(Collection framework)中看到泛型的动机.例如,Map 类允许您向一个 Map 添加任意类的对象,即使最常见的情况是在给定映射(map)中保存某个特定类型(比如 String)的对象. 因为 Map.get(

  • 浅谈C#泛型的用处与特点

    泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个新功能.泛型将类型参数的概念引入 .NET Framework,类型参数使得设计如下类和方法成为可能:这些类和方法将一个或多个类型的指定推迟到客户端代码声明并实例化该类或方法的时候.例如,通过使用泛型类型参数 T,您可以编写其他客户端代码能够使用的单个类,而不致引入运行时强制转换或装箱操作的成本或风险,如下所示: 复制代码 代码如下: // Declare the generic class public class Gener

  • C#泛型概念的简介与泛型的使用

    C# 泛型(Generic) 定义:泛型允许我们延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候.也就是说,泛型是可以与任何数据类型一起工作的类或方法. 泛型的使用:当我们的类/方法不需要关注调用者传递的实体是什么,这个时候就可以使用泛型. 泛型的特性: 使用泛型是一种增强程序功能的技术,具体表现在以下几个方面: 它有助于实现代码的重用.保护类型的安全以及提高性能. 我们可以创建泛型集合类.在 System.Collections.Generic 命名空间中包含了一些新

  • 实例讲解C# 泛型(Generic)

    泛型(Generic) 允许您延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候.换句话说,泛型允许您编写一个可以与任何数据类型一起工作的类或方法. 您可以通过数据类型的替代参数编写类或方法的规范.当编译器遇到类的构造函数或方法的函数调用时,它会生成代码来处理指定的数据类型.下面这个简单的实例将有助于您理解这个概念: using System; using System.Collections.Generic; namespace GenericApplication {

  • 详细介绍C# 泛型

    在C#开发中,必不可少的要用到泛型.泛型是.NET2.0版本就有的,它广泛应用于C#框架中容器的使用中.下面我们来详细介绍一下. 一.泛型的主要优势 1.性能更高. 2.类型更安全. 3.代码更多的重用和扩展性. 二.泛型的基本使用 泛型的一个主要优点是性能,我们来看下面的例子: static void Main(string[] args) { //不是泛型的集合类 ArrayList list = new ArrayList(); //添加一个值类型 装箱操作 list.Add(12); /

  • C#之泛型详解

    目录 一.泛型的特性 1.性能 2.类型安全 3.二进制代码的重用 4.代码的扩展 5.命名约定 二.使用类型 1.先创建一个非泛型的简化链表类. 2.下面编写一个泛型版本 三.泛型类的功能 1.默认值 2.约束 3.继承 4.静态成员 四.泛型接口 五.泛型结构 六.泛型方法 1.带约束的泛型方法 2.带委托的泛型方法 3.泛型方法规范 泛型不仅是C#的一部分,而且与程序集中的IL代码紧密地集成.有了泛型,就可以创建独立于被包含类型的类和方法.这样就可以不必给不同的类型编写功能相同的许多方法或

随机推荐