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

背景

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

实现

  这里贴出具体的代码实现

using System;
using System.Collections.Generic;
using System.Linq;

namespace XXX.XXX.Core.Utils
{
  public class ItemsChangedEventArgs<T> : EventArgs
  {
    public IList<T> RemovedItems { get; private set; }
    public IList<T> AddedItems { get; private set; }
    public ItemsChangedEventArgs(IList<T> removedItems, IList<T> addItems)
    {
      RemovedItems = removedItems;
      AddedItems = addItems;
    }
  }

  public delegate void ListItemsChangedEventHandler<T>(object sender, ItemsChangedEventArgs<T> args);

  public class NotifyList<T> : List<T>
  {
    public static NotifyList<T> Empty
    {
      get { return new NotifyList<T>(); }
    }

    public event ListItemsChangedEventHandler<T> ItemsChanged;
    protected void OnItemsChanged(IList<T> removedItems, IList<T> addedItems)
    {
      ListItemsChangedEventHandler<T> temp = ItemsChanged;
      temp?.Invoke(this, new ItemsChangedEventArgs<T>(removedItems, addedItems));
    }

    public new void Add(T item)
    {
      base.Add(item);

      OnItemsChanged(Empty, new List<T> { item });
    }

    public new void AddRange(IEnumerable<T> collection)
    {
      base.AddRange(collection);

      OnItemsChanged(Empty, collection.ToList());
    }

    public new void Clear()
    {
      T[] array = new T[this.Count];
      this.CopyTo(array);

      base.Clear();

      OnItemsChanged(array.ToList(), Empty);
    }

    public new bool Remove(T item)
    {
      bool ret = base.Remove(item);
      if (ret) OnItemsChanged(new List<T> { item }, Empty);
      return ret;
    }

    public new int RemoveAll(Predicate<T> match)
    {
      IList<T> removedItems = FindAll(match);

      int count = base.RemoveAll(match);
      if (removedItems.Count != count)
      {
        throw new Exception("[NotifyList][RemoveAll][The number of elements found by the predicate does not match the number of elements removed.]");
      }

      OnItemsChanged(removedItems, Empty);
      return count;
    }

    public new void RemoveAt(int index)
    {
      T removedItem = this[index];
      base.RemoveAt(index);
      OnItemsChanged(new List<T> { removedItem }, Empty);
    }

    public new void RemoveRange(int index, int count)
    {
      IEnumerable<T> range = this.Skip(index + 1).Take(count);
      base.RemoveRange(index, count);
      OnItemsChanged(range.ToList(), Empty);
    }
  }
}

注意事项

  1 基类中Add这些方法都是非虚方法,这里不能使用重载,所以在自己实现的每一个方法中需要使用 new 关键字进行覆盖。

2  在具体使用的时候需要订阅ItemsChanged事件。

以上就是C# 如何实现一个带通知的List<T>的详细内容,更多关于C# 实现一个带通知的List<T>的资料请关注我们其它相关文章!

(0)

相关推荐

  • 关于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#基础教程之IComparable用法,实现List<T>.sort()排序

    List<T>.sort()可以实现对T的排序,比如List<int>.sort()执行后集合会按照int从小到大排序.如果T是一个自定义的Object,可是我们想按照自己的方式来排序,那该怎么办呢,其实可以用过IComparable接口重写CompareTo方法来实现.流程如下: 一.第一步我们申明一个类Person但是要继承IComparable接口: 复制代码 代码如下: using System; using System.Collections.Generic; usin

  • 浅谈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#常见的几种集合 ArrayList,Hashtable,List<T>,Dictionary<K,V> 遍历方法对比

    一.先来分别介绍一下ArrayList,Hashtable,List<T>,Dictionary<K,V> 1.ArrayList动态数组,保存值的时候比较好用 2.Hashtable以存储键值对的方式存储.value,和key 3.List<T> 和 Dictionary<K,V> 应该是泛型吧,可以保存实体类 二.各种集合的遍历方法演示 1.ArrayList ArrayList list = new ArrayList(); //for遍历 for (

  • C#中将DataTable转化成List<T>的方法解析

    前言 通常在DAL层我们都需要把DataTable转换为List<T>让调用者尽可能的好用,尽量的不用关心数据库的字段等,所以我们一般传过去的都是List<T>而不是DataTable. 泛型的好处: 它为使用c#语言编写面向对象程序增加了极大的效力和灵活性.不会强行对值类型进行装箱和拆箱,或对引用类型进行.当涉及到两者之间的转换时,就显得有些较为繁琐.这个其中的问题主要在两者的存储方式,DataTable的存储方式采用一种二维表的方式进行数据的存储操作,DataTable表示内存

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

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

  • C#将DataTable转化为List<T>

    在使用三层架构开发一个网站时,希望把DataTable对象转换为List<T>对象,于是在网上找资料,总结一个比较方便的方法来实现--使用反射. 思路: 初始化一个List<T>对象 获取到T所有的属性,初始化一个T对象 遍历所有属性,如果DataTable中含有相应属性的值则为T对象赋值,如果没有对应的列则检查数据模型是否定义有误(属性名与列名比较时不区分大小写) 将T对象添加到List<T>对象中 总体代码: 反射获取到的属性信息 DataTable中的列信息,对比

  • 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> Contains<T>()的用法小结

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

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

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

  • vue从零实现一个消息通知组件的方法详解

    本文实例讲述了vue从零实现一个消息通知组件的方法.分享给大家供大家参考,具体如下: 利用vue从零实现一个消息通知组件 平时,我们肯定用过类似element-ui,antd等一些UI框架,感受它们带给我们的便利.但当我们的需求或者设计这些框架内置的相差太大,用起来,就会觉得特别别扭,这时候,就有必要自己来重新造轮子. 重新造轮子,有几个好处,1.所有代码都是服务你的业务,没有太多用不上的东西.2.代码是由自己维护,而不是第三方,方便维护.3.提升自己的视野,让自己站在更高的角度来看问题. 好了

  • 弹出一个带确认和取消的dialog实例

    实例如下: /** * 弹出一个带确认和取消的dialog * @param context * @param title * @param msg * @param okbutton * @param ok 点击确定事件 * @param nobutton * @param no 点击取消事件 * @return */ public static AlertDialog openConfirmDialog(Context context, String title, String msg, S

  • JavaScript实现一个带AI的井字棋游戏源码

    最近有一门课结束了,需要做一个井字棋的游戏,我用JavaScript写了一个.首先界面应该问题不大,用html稍微写一下就可以.主要是人机对弈时的ai算法,如何使电脑方聪明起来,是值得思考一下的.开始游戏后,由玩家先行.那么站在计算机的角度,可以对多种情况进行分析,并按照重要程度赋予权值. 情况如下: 1.同一排(行.列.对角线)有且只有两个棋子,并且都是自己的,只要再进一步就能获胜,那么剩下的那个位置权值最高,优先级最大.赋予一级权值. 2.同一排(行.列.对角线)有且只有两个棋子,并且都是对

  • 基于PyQt5制作一个windows通知管理器

    前几天看到一个python框架win10toast,它可以用来做windows的消息通知功能.通过设定通知的间隔时间来实现一些事件通知的功能,比如可以可以提醒一头扎进代码编写过程的我们按时喝水. 界面布局采用的依旧是pyqt5的ui设计,使用界面化直接设置好想要提示的内容和时间就可以给我们定时的发通知了. UI相关的部分的还是这几个常用的组件包. from PyQt5.QtGui import * # UI 界面相关 from PyQt5.QtCore import * # 核心组件包 from

  • 基于Python3制作一个带GUI界面的小说爬虫工具

    目录 效果图 开发完成后的界面 采集过程界面 采集后存储 主要功能 用到的第三方模块 打包为 exe 命令 全部源码 效果图 最近帮朋友写个简单爬虫,顺便整理了下,搞成了一个带GUI界面的小说爬虫工具,用来从笔趣阁爬取小说. 开发完成后的界面 采集过程界面 采集后存储 主要功能 1.多线程采集,一个线程采集一本小说 2.支持使用代理,尤其是多线程采集时,不使用代理可能封ip 3.实时输出采集结果 使用 threading.BoundedSemaphore() pool_sema.acquire(

  • 教你创建一个带诊断工具的.NET镜像

    目录 现阶段的问题 解决方案 常用的工具 总结 现阶段的问题 现在是云原生和容器化时代,.NET Core对于云原生来说有非常好的兼容和亲和性,dotnet社区以及微软为.NET Core提供了非常方便的镜像容器化方案.所以现在大多数的dotnet程序都是部署在各种容器化环境中,比如我们常见的Docker. 微软官方为.NET提供的许多Docker镜像,让我们可以很方便的创建容器化的.NET应用.如下所示就是部分官方提供的不同操作系统的镜像. 其它更详细的内容大家可以点击后面的网址查看:http

  • Python实现一个带权无回置随机抽选函数的方法

    需求 有一个抽奖应用,从所有参与的用户抽出K位中奖用户(K=奖品数量),且要根据每位用户拥有的抽奖码数量作为权重. 如假设有三个用户及他们的权重是: A(1), B(1), C(2).希望抽到A的概率为25%,抽到B的概率为25%, 抽到C的概率为50%. 分析 比较直观的做法是把两个C放到列表中抽选,如[A, B, C, C], 使用Python内置的函数random.choice[A, B, C, C], 这样C抽到的概率即为50%. 这个办法的问题是权重比较大的时候,浪费内存空间. 更一般

  • javascript实现的一个带下拉框功能的文本框

    有时我们需要一个可选的下拉框来选取内容,但是但是又有可以自定义输入的需求.对于这种需求,大部分网站使用的都是一个下拉框和一个 input text ,并列或分行给出选择.那么,我们希望它看上去像一个可以输入也可以选择的下拉框,那该如何做呢? 其实我们可以通过 css position 定位及少许的 javascript 代码,模拟出来这种效果. 复制代码 代码如下: <!DOCTYPE html><html><head> <title>可编辑可选择的下拉框&

  • 一个带采集远程文章内容,保存图片,生成文件等完整的采集功能

    复制代码 代码如下: '================================================== '函数名:GetHttpPage '作 用:获取网页源码 '参 数:HttpUrl ------网页地址 '================================================== Function GetHttpPage(HttpUrl) If IsNull(HttpUrl)=True Or Len(HttpUrl)<18 Or HttpUr

随机推荐