因为平时使用 System.Collections.CollectionBase 时候发现有些不足,故而作了一个扩展的 CollectionBaseEx,代码如下,因为注释较多,故不再解释。

/**//// <summary>
/// 增强的 CollectionBase ,支持排序,和更多的通知
/// </summary>
public class CollectionBaseEx : IList

{
private ArrayList m_InnerList;
private bool m_Duplicated; // 是否允许重复元素
private bool m_Sorted; // 是否允许排序
private IComparer m_Comparer; // 排序时候使用的比较器
private bool m_SingleCheck; // 是否在处理时候要处理单个元素,引发Include/Exclude事件


/**//// <summary>
/// 默认构造函数
/// </summary>
protected CollectionBaseEx()

{
m_InnerList = new ArrayList();
m_Duplicated = true;
m_Sorted = false;
m_Comparer = System.Collections.Comparer.Default;
m_SingleCheck = false;
}


/**//// <summary>
/// 构造函数
/// </summary>
/// <param name="duplicated">是否允许重复元素</param>
/// <param name="singleCheck">是否对每一个元素进行检查并发出通知</param>
/// <param name="sorted">对值进行排序</param>
/// <param name="comparer">比较器</param>
protected CollectionBaseEx(bool duplicated, bool singleCheck, bool sorted, IComparer comparer) : this()

{
m_Duplicated = duplicated;
m_Sorted = sorted;
m_Comparer = comparer;
m_SingleCheck = singleCheck;
}


/**//// <summary>
/// 操作接口,能够触发各种通知
/// </summary>

protected IList List
{ get
{ return this; } }


/**//// <summary>
/// 实际存放数据的容器
/// </summary>
protected ArrayList InnerList

{

get
{ return m_InnerList; }
set

{
if (value == null)
throw new ArgumentNullException("value can not be null", "value");
m_InnerList = value;
}
}


/**//// <summary>
/// 允许重复元素
/// </summary>

protected bool Duplicated
{ get
{ return m_Duplicated; } set
{ m_Duplicated = value; } }


/**//// <summary>
/// 排序
/// </summary>

protected bool Sorted
{ get
{ return m_Sorted; } set
{ m_Sorted = value; } }


/**//// <summary>
/// 对每一个元素进行检查并发出通知
/// </summary>

protected bool SingleCheck
{ get
{ return m_SingleCheck; } set
{ m_SingleCheck = value; } }


/**//// <summary>
/// 比较器
/// </summary>

protected IComparer Comparer
{ get
{ return m_Comparer; } set
{ m_Comparer = value; } }



callback#region callback


/**//// <summary>
/// 清除所有元素之前的通知
/// </summary>

protected virtual void OnClear()
{}

/**//// <summary>
/// 所有元素清除成功之后的通知
/// </summary>

protected virtual void OnClearComplete()
{}

/**//// <summary>
/// 插入元素之前的通知
/// </summary>
/// <param name="index">元素插入位置</param>
/// <param name="value">插入的值</param>

protected virtual void OnInsert(int index, object value)
{}

/**//// <summary>
/// 元素插入成功之后的通知
/// </summary>
/// <param name="index">元素插入位置</param>
/// <param name="value">插入的值</param>

protected virtual void OnInsertComplete(int index, object value)
{}

/**//// <summary>
/// 删除元素之前的通知
/// </summary>
/// <param name="index">要删除元素的位置</param>
/// <param name="value">要删除的元素</param>

protected virtual void OnRemove(int index, object value)
{}

/**//// <summary>
/// 删除元素之后的通知
/// </summary>
/// <param name="index">要删除元素的位置</param>
/// <param name="value">要删除的元素</param>

protected virtual void OnRemoveComplete(int index, object value)
{}

/**//// <summary>
/// 设置元素的值之前的通知
/// </summary>
/// <param name="index">元素的位置</param>
/// <param name="oldValue">该位置的当前的值</param>
/// <param name="newValue">将要存放到该位置的新值</param>
/// <remarks>如果<see cref="Sorted"/>为真,则设置成功之后的元素会移动到正确的位置上去</remarks>

protected virtual void OnSet(int index, object oldValue, object newValue)
{}

/**//// <summary>
/// 设置元素的值成功之后的通知
/// </summary>
/// <param name="index">元素位置</param>
/// <param name="oldValue">该位置以前的值</param>
/// <param name="newValue">该位置当前的值</param>
/// <remarks>如果<see cref="Sorted"/>为真,则设置成功之后的元素会移动到正确的位置上去</remarks>

protected virtual void OnSetComplete(int index, object oldValue, object newValue)
{}


/**//// <summary>
/// 通知对元素进行正确性检查
/// </summary>
/// <param name="value">将要存放的值</param>

protected virtual void OnValidate(object value)
{}


/**//// <summary>
/// 将要把元素存放到容器之前的通知
/// </summary>
/// <param name="value">将要存放的值</param>

protected virtual void OnInclude(object value)
{}


/**//// <summary>
/// 将要把元素从容器中脱离之前的通知
/// </summary>
/// <param name="value">将要脱离容器的值</param>

protected virtual void OnExclude(object value)
{}

#endregion


internal logic#region internal logic

private void BeforeClear()

{
if( m_SingleCheck )

{
int index = 0;
try

{
while( index < m_InnerList.Count)

{
OnExclude(m_InnerList[index]);
++ index;
}
}
catch(Exception)

{
while( --index >= 0 )
OnInclude(m_InnerList[index]);
throw;
}
}

OnClear();
}

private void AfterClearComplete()

{
OnClearComplete();
}

private void BeforeInsert(int index, object value)

{
if( m_Sorted )
throw new InvalidOperationException("排序状态下不能使用");
if( this.m_SingleCheck )
OnInclude(value);
OnInsert(index, value);
}

private void AfterInsertComplete(int index, object value)

{
OnInsertComplete(index, value);
}

private void BeforeRemove(int index, object value)

{
if( m_SingleCheck )
OnExclude(value);
OnRemove(index, value);
}

private void AfterRemoveComplete(int index, object value)

{
OnRemoveComplete(index, value);
}

private void BeforeSet(int index, object oldValue, object newValue)

{
if( m_SingleCheck )
OnInclude(newValue);
OnSet(index, oldValue, newValue);
}

private void AfterSetComplete(int index, object oldValue, object newValue)

{
if( m_SingleCheck )
OnExclude(oldValue);
OnSetComplete(index, oldValue, newValue);
}

private void CheckValidate(object value)

{
if (value == null)
throw new ArgumentNullException("value can not be null", "value");
if( !Duplicated
&& (( !m_Sorted && m_InnerList.IndexOf(value) != -1 )
|| (m_Sorted && m_InnerList.BinarySearch(value, m_Comparer) >= 0)
))
throw new ArgumentException("object exists");

OnValidate(value);
}

#endregion


IList 成员#region IList 成员


bool IList.IsReadOnly
{ get
{ return m_InnerList.IsReadOnly; } }

object IList.this[int index]

{

get
{ return m_InnerList[index]; }
set

{
CheckValidate(value);
object old = m_InnerList[index];
this.BeforeSet(index, old, value);
m_InnerList[index] = value;
try

{
this.AfterSetComplete(index, old, value);
if( m_Sorted ) // 移动到正确位置

{
m_InnerList.RemoveAt(index);
int pos = m_InnerList.BinarySearch(value, m_Comparer);
if( pos < 0 ) pos = ~pos;
m_InnerList.Insert(pos, value);
}
}
catch (Exception)

{
m_InnerList[index] = old;
throw;
}
}
}

public void RemoveAt(int index)

{
object obj = m_InnerList[index];

this.BeforeRemove(index, obj);
m_InnerList.RemoveAt(index);
this.AfterRemoveComplete(index, obj);
}

void IList.Insert(int index, object value)

{
CheckValidate(value);
this.BeforeInsert(index, value);
m_InnerList.Insert(index, value);
try

{
this.AfterInsertComplete(index, value);
}
catch (Exception)

{
m_InnerList.RemoveAt(index);
throw;
}
}

void IList.Remove(object value)

{
int index = m_InnerList.IndexOf(value);
if( index < 0 )
throw new ArgumentException("object not found");
this.BeforeRemove(index, value);
m_InnerList.Remove(value);
this.AfterRemoveComplete(index, value);
}

bool IList.Contains(object value)

{
return m_InnerList.Contains(value);
}

public void Clear()

{
this.BeforeClear();
m_InnerList.Clear();
this.AfterClearComplete();
}

int IList.IndexOf(object value)

{
return m_InnerList.IndexOf(value);
}

int IList.Add(object value)

{
CheckValidate(value);
int index = m_InnerList.Count;
if( m_Sorted )

{
index = m_InnerList.BinarySearch(value, m_Comparer);
if( index < 0 ) index = ~index;
}
this.BeforeInsert(index, value);
if( !m_Sorted )
index = m_InnerList.Add(value);
else
m_InnerList.Insert(index, value);

try

{
this.AfterInsertComplete(index, value);
}
catch (Exception)

{
m_InnerList.RemoveAt(index);
throw;
}
return index;
}


bool IList.IsFixedSize
{ get
{ return m_InnerList.IsFixedSize; } }

#endregion


ICollection 成员#region ICollection 成员


bool ICollection.IsSynchronized
{ get
{ return m_InnerList.IsSynchronized; } }


public int Count
{ get
{ return m_InnerList.Count; } }

void ICollection.CopyTo(Array array, int index)

{
m_InnerList.CopyTo(array, index);
}


object ICollection.SyncRoot
{ get
{ return m_InnerList.SyncRoot; } }


#endregion


IEnumerable 成员#region IEnumerable 成员

public IEnumerator GetEnumerator()

{
return m_InnerList.GetEnumerator();
}

#endregion

public IEnumerator GetEnumerator(int index, int count)

{
return m_InnerList.GetEnumerator(index, count);
}

}

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了