【C#2.0】发挥匿名委托的威力!
今天,我尝试在C#2.0中使用匿名委托模拟C#3.0中Where、Select等查询方法的实现。我将所有的查询方法作为静态方法在GenericHepler静态类中实现。
之前,我们先定义泛型委托:
这个委托在后面的实现中需要用到。
作为基础,首先,我们需要实现ForSpecification方法,该方法的含义是:对集合中满足指定条件的元素执行指定方法调用。
/// ForSpecification 对集合中满足predicate条件的元素执行action。如果没有条件,predicate传入null。
/// </summary>
public static void ForSpecification<TSource>(IEnumerable<TSource> collection, Action<TSource> action, Predicate<TSource> predicate)
{
if (predicate == null)
{
foreach (TSource obj in collection)
{
action(obj);
}
return;
}
foreach (TSource obj in collection)
{
if (predicate(obj))
{
action(obj);
}
}
}
有了ForSpecification的实现,我们就可以在其基础上实现ForEach和ForFirstSpecification:
/// <summary>
/// ForEach 对集合中的每个元素执行action。
/// </summary>
public static void ForEach<TSource>(IEnumerable<TSource> collection, Action<TSource> action)
{
GenericHepler.ForSpecification<TSource>(collection, action, null);
}
#endregion
#region ForFirstSpecification
/// <summary>
/// ForSpecification 对集合中第一个满足predicate条件的元素执行action。如果没有条件,predicate传入null。
/// </summary>
public static void ForFirstSpecification<TSource>(IEnumerable<TSource> collection, Action<TSource> action, Predicate<TSource> predicate)
{
if (predicate == null)
{
foreach (TSource obj in collection)
{
action(obj);
break;
}
}
else
{
foreach (TSource obj in collection)
{
if (predicate(obj))
{
action(obj);
break;
}
}
}
}
#endregion
有了ForSpecification,我们就可以实现查询方法Where:
/// <summary>
/// Where 从集合中选取符合条件的元素
/// </summary>
public static IList<TSource> Where<TSource>(IEnumerable<TSource> source, Predicate<TSource> predicate)
{www.elivn.com
IList<TSource> list = new List<TSource>();
GenericHepler.ForSpecification(source, delegate(TSource ele) { list.Add(ele); } , predicate);
return list;
}
#endregion
对于C#3.0中的Select方法,其实现需要匿名类型的支持,而C#2.0中不支持匿名类型,所以,我用泛型来代替。我使用ConvertSpecification来模拟Select实现:
/// <summary>
/// ConvertSpecification 将source中的符合predicate条件元素转换为TResult类型
/// </summary>
public static IList<TResult> ConvertSpecification<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> converter, Predicate<TSource> predicate)
{
IList<TResult> list = new List<TResult>();
GenericHepler.ForSpecification<TSource>(source, delegate(TSource ele) { list.Add(converter(ele)); } ,predicate);
return list;
}
#endregion
converter委托用于从TSource类型对象构造TResult类型的对象。
有了ConvertSpecification实现,我们就可以在其上继续实现ConvertAll和ConvertFirstSpecification:
/// <summary>
/// ConvertAll 将source中的每个元素转换为TResult类型
/// </summary>
public static IList<TResult> ConvertAll<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> converter)
{
return GenericHepler.ConvertSpecification<TSource, TResult>(source, converter, null);
}
#endregion
#region ConvertFirstSpecification
/// <summary>
/// ConvertSpecification 将source中的符合predicate条件的第一个元素转换为TResult类型
/// </summary>
public static TResult ConvertFirstSpecification<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> converter, Predicate<TSource> predicate)
{
TSource target = GenericHepler.GetFirstSpecification<TSource>(source, predicate);
if (target == null)
{
return default(TResult);
}
return converter(target);
}
#endregion
有了上面的基础,我们还可以实现ContainsSpecification方法:
/// <summary>
/// ContainsSpecification 集合中是否包含满足predicate条件的元素。
/// </summary>
public static bool ContainsSpecification<TSource>(IEnumerable<TSource> source, Predicate<TSource> predicate, out TSource specification)
{
specification = default(TSource);
foreach (TSource element in source)
{
if (predicate(element))
{
specification = element;
return true;
}
}
return false;
}
#endregion
#region ContainsSpecification
/// <summary>
/// ContainsSpecification 集合中是否包含满足predicate条件的元素。
/// </summary>
public static bool ContainsSpecification<TSource>(IEnumerable<TSource> source, Predicate<TSource> predicate)
{
TSource specification;
return GenericHepler.ContainsSpecification<TSource>(source, predicate, out specification);
}
#endregion
代码中的注释已经将各个方法的用途说得非常清楚,下面我们举两个例子来看看如何使用它们以发挥它们的威力!
例子一:比如,我们要从当前玩家(IPlayer)列表中找出所有年龄大于30岁的玩家的ID,通常这样做:
{
IList<string> results = new List<string>();
foreach (IPlayer player in this.playerList)
{
if (player.Age > 30)
{
results.Add(player.ID);
}
}
return results;
}
如果使用上面我们封装的API,则可以非常简单地达到目的:
{
return GenericHepler.ConvertSpecification<IPlayer, string>(this.playerList, delegate(IPlayer player) { return player.ID; } , delegate(IPlayer player) {return player.Age > 30 });
}
一句搞定。
例子二:我们要从当前的玩家字典(Dictionary)中取出所有ID不是指定集合中的ID的其它玩家列表。
通常,我们可以这样做:
{
IList<IPlayer> partnersList = new List<IPlayer>();
foreach (string userID in this.dicPlayers.Keys)
{
bool exclude = false;
foreach (string excludedUser in excludedUserIDs)
{
if (userID == excludedUser)
{
exclude = true;
break;
}
}
if (!exclude)
{
partnersList.Add(this.dicPlayers[userID]);
}
}
return partnersList;
}
使用上面我们封装的API,则非常简单:
{
return GenericHepler.Where<IPlayer>(this.dicPlayers.Values, delegate(IPlayer player) { return !GenericHepler.ContainsSpecification<string>(excludedUserIDs, delegate(string id) { return id == player.UserID; }); });
}
灵活地使用这些API,我们可以非常简洁地操作集合中的元素。
最后给出GenericHepler类的源码下载,其中还包含了几个未介绍的实用的API。
转载于:https://www.cnblogs.com/seoxs/archive/2011/04/20/2021838.html
【C#2.0】发挥匿名委托的威力!相关推荐
- 用一个实例说说委托,匿名委托,Lamda表达式
C#到3.0中一直都在不断地提高,增加了很多特性,从2.0的匿名委托到现在的LAMDA表达式,为的就是让大家觉得语言越来越人性化.以下是我写的一个小DEMO,用来简单示例一下他们之间的关系.非常简单易 ...
- Delegate,Action,Func,匿名方法,匿名委托,事件
一.委托Delegate 一般的方法(Method)中,我们的参数总是string,int,DateTime...这些基本的数据类型(或者没有参数),比如 [c-sharp] view plainco ...
- Delegate,Action,Func,匿名方法,匿名委托,事件 (转载)
Delegate,Action,Func,匿名方法,匿名委托,事件 (转载) 一.委托Delegate 一般的方法(Method)中,我们的参数总是string,int,DateTime...这些基本 ...
- C# 匿名委托、匿名方法、匿名对象、Lambda表达式
C# 匿名委托.匿名方法.匿名对象.Lambda表达式 原文:C# 匿名委托.匿名方法.匿名对象.Lambda表达式 一.匿名类型 可通过使用 new 运算符和对象初始值创建匿名类型. 示例: var ...
- C#多线程|匿名委托传参数|测试您的网站能承受的压力|附源代码
源代码下载:http://www.sufeinet.com/thread-13-1-1.html 引言 我们一直在做网站,但在我河南这块,对测试工作,特别是压力测试一般都不怎么在意,都是自己访问一下速 ...
- unity3d C#用匿名委托循环注册按钮点击事件报错:索引超界 ArgumentOutOfRangeException: Index was out of range. Must be non-ne
unity3d C#用匿名委托循环注册按钮点击事件报错:索引超界 ArgumentOutOfRangeException: Index was out of range. Must be non-ne ...
- C#委托,多播委托,匿名委托,事件
委托 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递.事件是一种特殊的委托. 委托是方法的抽象,它存储的就是一系列具有相同签名和返回类型的方法的地址.调用委托的时候,委 ...
- 分配委托、匿名委托、委托
分配委托(将命名方法分配给其委托) using System;public class GenericFunc {public static void Main(){// Instantiate de ...
- NEXT社区小课堂 | 第四课:dBFT 2.0详解 | 委托拜占庭容错:技术细节、挑战和前景...
NEXT社区 | 小课堂 由于近期NEXT社区加入很多新的小伙伴,有在校大学生,有对区块链感兴趣的传统企业从业者.为了更方便.更系统的让NEXT社区的伙伴们了解NEO的技术知识,因此我们开设了小课堂, ...
最新文章
- jQuery的attr方法处理checkbox的问题
- Android--Matrix图片变换处理
- 2021的第二封拒信,来自斯坦福电气工程
- Rancher2.0中邮件通知的设置
- 深入浅出 Linux 惊群:现象、原因和解决方案
- (一)导学(Javascript设计模式系统讲解与应用)
- NA-NP-IE系列实验5:配置文件的备份和IOS 的备份
- linux增加 inode空间,linux 增加inode 的方法
- sigmoid激活函数
- 使用公开页实现扫码签到功能
- Google 应用与游戏出海 4 月刊: 带您连线 GDC,赢在发布前!
- Java小白 前端后端开发 环境搭建【jdk+idea+webstorm+maven+nodejs+vue+mysql】
- 怎么验证mysql安装成功_mysql如何验证是否安装成功
- 响应式网站如何实现?
- vmware虚拟机无法u盘启动的解决办法
- java.sql.SQLException: Unable to load authentication plugin ‘caching_sha2_password‘.
- 网络安全--入侵攻击类型
- 修复计算机黑屏,笔记本电脑黑屏怎么修复 笔记本电脑黑屏修复方法【详解】...
- OMRON E6B2-CWZ6C
- 公交卡非法充值与其计费系统之分析
热门文章
- 《计算机导论》课程论文,计算机导论课程论文
- js清空文本框的值_一个Vue.js实例控制字变大变小,含样式操作,flex布局。「603」...
- imgaug批量椒盐噪声 python_python图像扩增-imgaug
- ubuntu安装python_Linux下的Python开发配置鸭
- 基于Java+SpringBoot+vue+element等动物救助平台设计和实现
- java打印等腰梯形
- java 堆排序方式_幾種排序方式的java實現(02:希爾排序,歸並排序,堆排序)
- mysql无法启动修复_记一次MySQL无法启动及修复经历
- C++ auto和decltype关键字
- int mysql_「MYSQL」MYSQL中的int(11)到底代表什么意思?