在前一篇博文中,我们自定义了类型User和它的集合类Users,实现对这个集合的添加,删除,检索,修改(是先检索出单个User,然后直接修改这个检索出来的值,这是因为User是引用类型)。在上一篇博文中,我们是做了个索引器,通过用户的ID来作为索引的条件。其实在我们在做查询时,不只只是需要UserID作为查询条件,可能需要UserName,有时不只只是一个件条,有可能是两个条件,如果有一个我们随心所欲的查询就好了。
delegate bool Fun(User user);
这个委托是接收一个User类型的参数,以一个bool类型作为返回值。
public User First(Fun predicate)
foreach (User user in users)
方法的参数是接收一个Fun的委托类型,也就是一个方法,参数predicate在First内就代表一个方法,First方法体是循环Users内users这个泛型的List集合,把每个子项当参数传进predicate方法,如果predicate方法返回值为true,就把这个泛型集合的中的User当成First方法的返回值返回去,总而言之,First方法是从集合查找满足predicate方法的用户,并返回。
再次,我们来使用一下Users中的这个First方法:
Users users = new Users();
user1.PassWord = "111111";
MessageBox.Show(users.First(user => user.ID == 1).ToString());//这是在WinForm下面的显示
user => user.ID == 1代表一个方法,不过是匿名方法,前面一个user是参数,后面的user.ID==1的返回值作为匿名方法的返回值,这个匿名方法,与委托Fun正好对应上,即参数是User,返回值是bool。
当然,user=>user.ID==1只是一种写法,我们还可以写成user=>user.UserName==”aaaa”,或写成user=>user.UserNmae==”aaaa”&&user.PassWord==”111111”,“=>”符号右边的表达式只要是个bool类型就可以。正是因为这个匿名方法,我们查询的条件就变成灵活的了,而不用专门定义不同类型的查询方法来适应不同的查询了。
也可能,这时,你已经想到,在LINQ中,也是这样实现的,对,这种写法与LINQ中的查询语法是一样的。
不过,在LINQ中,这些扩展了的查询语法的方法,不是在具体的某一个集合类中定义的,而是在一个静态类中定义的,这个静态类叫Enumerable,它是一个扩展方法的类,内部包括很多个扩展方法,比如内部的
换言之,如果我们把Users也实现IEnumerable<T>接口,Users也自然就拥有像First,Where这些查询语法的方法了。而不像上面那样(Users类中的First方法),需要自己一个一个去实现所有的扩展方法了。
但由于IEnumerable<T>是个泛型的接口,把以Users类也就需要定义成泛型了,为了使Users专用,我们在Users定义时,使用了泛型的约束,T是User类,或它的子类都可以。
class Users<T> : IEnumerable<T>, IListSource, IEnumerable where T : User
/// 实现Ienumerable<T>的GetEnumerator方法
IEnumerator<T> IEnumerable<T>.GetEnumerator()
for (int i = 0; i < users.Count; i++)
List<T> users = new List<T>();
/// <param name="i">用户ID</param>
foreach (T user in users)
if (Convert.ToInt32(user.GetType().GetProperty("ID").GetValue(user, null)) == ID)
for (int i = 0; i < users.Count; i++)
if (Convert.ToInt32(users[i].GetType().GetProperty("ID").GetValue(users[i], null)) == (Convert.ToInt32(value.GetType().GetProperty("ID").GetValue(value, null))))
/// <param name="user">用户</param>
public void AddUser(T user)
/// <param name="user">用户</param>
public void RemoveUser(T user)
public bool ContainsListCollection
public System.Collections.IList GetList()
public IEnumerator GetEnumerator()
for (int i = 0; i < users.Count; i++)
其实如果限制了T为User类或它的子类,在一定程度上这个Users类的使用就很受限制了,如果不限制T受User约束,那么Users就不一定是User的集合了,因为T决定了这个集合是什么类型的集合,此时的Users<T>更像List<T>了(Users<T>中的成员,还是要少于List<T>中的成员的,因数在Users<T>中我们仅定义了Add,Remove,Count,索引器等成员)。
通过上面的例子,我们能了解到,查询条件可以自定义,也可以通过继承IEnumerable<T>接口来扩展查询,这要根据自己的应用决定使用那一技术了。
本文转自桂素伟51CTO博客,原文链接:http://blog.51cto.com/axzxs/534778 ,如需转载请自行联系原作者