基础知识:创建自定义集合
很多时候我们需要创建自己的集合来实现特殊的功能,比如说在操作集合的时候为某些动作添加侦听事件,这时可通过实现IEnumerable接口来创建一个自定义集合,并且可以很方便的进行扩展,作为基础储备,先实施一个简单的自定义集合,实现其添加、移除、查找、遍历功能。
要实现添加、移除、查找,需求一个容器用于存取集合内容,可选的很多,数组、列表、字典等都可以,这里选择列表来作为基础容器。
遍历需通过接口的GetEnumerator()来实现,下面是实现代码:
关于代码有两点说明:
1、Find方法中的Predicate<T>参数,这是一个委托参数,来看MSDN的解释:表示定义一组条件并确定指定对象是否符合这些条件的方法。
有点晦涩,实际它就是一个BOOL函数的委托,用于进行条件判断,这里可以是一个自定义的方法,也可以是一个Lambda表达式,待会再看看具体的示例。
2、关于GetEnumerator()中的yield关键字,其意义是在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。
用实际的例子来说明下其功用,比如说实现一个从1到10集合方法,先看看传统模式:
方法里用了一个INT数组来存值。
再来看看yield方式:
相同的方法,但代码中并没有显式的使用任何额外的集合来存值。
最后来看看自定义集合的使用方法,以一个对象模型集合来说明。
先定义一个对象模型:
创建一个简单的比较函数用于查找集合
最后是测试方法:
要实现添加、移除、查找,需求一个容器用于存取集合内容,可选的很多,数组、列表、字典等都可以,这里选择列表来作为基础容器。
遍历需通过接口的GetEnumerator()来实现,下面是实现代码:
public class ORMList<T> : IEnumerable<T>
{
private List<T> lisORM;
public ORMList()
{
lisORM = new List<T>();
}
public ORMList(IEnumerable<T> lisCustom)
{
lisORM = new List<T>(lisCustom);
}
/// <summary>
/// 索引器
/// </summary>
public T this[int index]
{
get
{
if (index >= 0 && index < lisORM.Count)
{
return lisORM[index];
}
return default(T);
}
set
{
lisORM[index] = value;
}
}
/// <summary>
/// 新增
/// </summary>
public void Add(T model)
{
lisORM.Add(model);
}
/// <summary>
/// 指定位置插入
/// </summary>
public void Insert(int index, T model)
{
lisORM.Insert(index, model);
}
/// <summary>
/// 移除
/// </summary>
public void Remove(T model)
{
lisORM.Remove(model);
}
/// <summary>
/// 指定位置移除
/// </summary>
public void RemoveAt(int index)
{
lisORM.RemoveAt(index);
}
/// <summary>
/// 查找单个元素
/// </summary>
public T Find(Predicate<T> match)
{
return lisORM.Find(match);
}
/// <summary>
/// 查找集合
/// </summary>
public ORMList<T> FindAll(Predicate<T> match)
{
return new ORMList<T>(lisORM.FindAll(match));
}
/// <summary>
/// 范围查找
/// </summary>
public ORMList<T> GetRange(int start, int count)
{
return new ORMList<T>(lisORM.GetRange(start, count));
}
/// <summary>
/// 集合大小
/// </summary>
public int Count
{
get
{
return lisORM.Count;
}
}
#region IEnumerable<T> 成员
public IEnumerator<T> GetEnumerator()
{
foreach (T model in lisORM)
{
yield return model;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
关于代码有两点说明:
1、Find方法中的Predicate<T>参数,这是一个委托参数,来看MSDN的解释:表示定义一组条件并确定指定对象是否符合这些条件的方法。
有点晦涩,实际它就是一个BOOL函数的委托,用于进行条件判断,这里可以是一个自定义的方法,也可以是一个Lambda表达式,待会再看看具体的示例。
2、关于GetEnumerator()中的yield关键字,其意义是在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。
用实际的例子来说明下其功用,比如说实现一个从1到10集合方法,先看看传统模式:
public IEnumerable OneToTen()
{
int[] arr = new int[10];
for (int i = 1; i <= 10; i++)
{
arr[i] = i;
}
return arr;
}
方法里用了一个INT数组来存值。
再来看看yield方式:
public IEnumerable OneToTen()
{
for (int i = 1; i <= 10; i++)
{
yield return i;
}
}
相同的方法,但代码中并没有显式的使用任何额外的集合来存值。
最后来看看自定义集合的使用方法,以一个对象模型集合来说明。
先定义一个对象模型:
public class TestModel
{
public string ID
{
get;
set;
}
public string NAME
{
get;
set;
}
}
创建一个简单的比较函数用于查找集合
/// <summary>
/// 自定义比较函数
/// </summary>
private static bool EqualFive(TestModel model)
{
return model.NAME == "5";
}
最后是测试方法:
public static void ORMListTest()
{
//添加集合
ORMList<TestModel> lisModel = new ORMList<TestModel>();
TestModel model = null;
for (int i = 0; i < 10; i++)
{
model = new TestModel();
model.ID = Guid.NewGuid().ToString();
model.NAME = i.ToString();
lisModel.Add(model);
}
Console.WriteLine("Get All:");
foreach(TestModel item in lisModel)
{
Console.WriteLine("ID = {0},NAME = {1}", item.ID, item.NAME);
}
//Lambda表达式方法查找单个元素
model = lisModel.Find(item => item.NAME == "5");
Console.WriteLine("FIND ITEM :ID = {0},NAME = {1}", model.ID, model.NAME);
//自定义比较函数查找单个元素
model = lisModel.Find(EqualFive);
Console.WriteLine("FIND ITEM :ID = {0},NAME = {1}", model.ID, model.NAME);
//查找集合
ORMList<TestModel> lisFind = lisModel.FindAll(item => int.Parse(item.NAME) > 5);
Console.WriteLine("Find Greater than 5:");
foreach (TestModel item in lisFind)
{
Console.WriteLine("ID = {0},NAME = {1}", item.ID, item.NAME);
}
}