让 C# 委托来帮你简化代码,学习使用 Func、Action 委托
2011-10-03 16:28 音乐让我说 阅读(4315) 评论(24) 编辑 收藏 举报为了方面大家更好地理解我写这篇文章的目的,这篇文章我会详细介绍我的代码,我有什么理解错误的,请大家不吝赐教。
首先我定义 2 个类。
公司类:
UserCompany.cs
class UserCompany { public int ID { get; set; } public string CompanyName { get; set; } public string CompanyDesc { get; set; } }
员工类:
UserInfo.cs
class UserInfo { public int ID { get; set; } public string UserName { get; set; } public int UserCompanyID { get; set; } public UserCompany UserCompany_UserCompanyID { get; set; } }
也许大家看到了,这里的员工类(UserInfo)有一个属性 UserCompanyID 来标记这个员工属于哪个公司。
同时也有一个属性 UserCompany_UserCompanyID 表示这个 UserCompanyID 对应的公司类(UserCompany)。
下面是一个方法来得到所有的公司,一般我们的数据是保存在数据库中的。为了演示,这里就不访问数据库了。
/// <summary> /// 得到所有的公司信息 /// </summary> /// <returns></returns> static IList<UserCompany> GetAllUserCompanys() { return new List<UserCompany>() { new UserCompany(){ ID = 1, CompanyName = "新浪", CompanyDesc = "新浪是个大公司" }, new UserCompany(){ ID = 2, CompanyName = "百度", CompanyDesc = "百度是个大公司" }, new UserCompany(){ ID = 3, CompanyName = "腾讯", CompanyDesc = "腾讯是个大公司" }, new UserCompany(){ ID = 4, CompanyName = "网易", CompanyDesc = "网易是个大公司" }, new UserCompany(){ ID = 5, CompanyName = "搜狐", CompanyDesc = "搜狐是个大公司" }, new UserCompany(){ ID = 6, CompanyName = "阿里巴巴", CompanyDesc = "阿里巴巴是个大公司" } }; }
同时也有一个方法来得到所有的员工。
/// <summary> /// 得到所有的员工信息 /// </summary> /// <returns></returns> static IList<UserInfo> GetAllUserInfos() { return new List<UserInfo>() { new UserInfo(){ ID = 1, UserName = "张三", UserCompanyID = 2 }, new UserInfo(){ ID = 2, UserName = "李四", UserCompanyID = 1 }, new UserInfo(){ ID = 3, UserName = "王五", UserCompanyID = 4 }, new UserInfo(){ ID = 4, UserName = "赵六", UserCompanyID = 1 }, new UserInfo(){ ID = 5, UserName = "杨七", UserCompanyID = 3 }, new UserInfo(){ ID = 6, UserName = "朱八", UserCompanyID = 1 }, new UserInfo(){ ID = 7, UserName = "孙九", UserCompanyID = 2 }, new UserInfo(){ ID = 8, UserName = "萧十一郎", UserCompanyID = 1 } }; }
一般如果我们得到了所有的员工的基本信息后,还想得到这些员工对应的公司信息,比如:公司名、公司描述等等。
怎么办呢?我的思路是,当我们得到这些员工的基本信息后,就能够得到每个员工对应的公司ID(UserCompanyID),
然后我在利用 Linq 取出这些公司ID(UserCompanyID),保存到一个可以枚举的集合中 IEnumerable<int>,然后去
数据库中取出这些公司ID(UserCompanyID)对应的公司信息。下面是代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConAppTest { class Program { static void Main(string[] args) { IList<UserInfo> users = GetAllUserInfos(); IEnumerable<int> userCompanyIds = users.Select<UserInfo, int>(u => u.UserCompanyID).Distinct(); IEnumerable<UserCompany> existsCompanys = GetCompanysByCompanyIds(userCompanyIds); foreach (UserCompany companyItem in existsCompanys) { if(companyItem == null) { continue; } Console.WriteLine(companyItem.CompanyName); } } /// <summary> /// 得到所有的员工信息 /// </summary> /// <returns></returns> static IList<UserInfo> GetAllUserInfos() { return new List<UserInfo>() { new UserInfo(){ ID = 1, UserName = "张三", UserCompanyID = 2 }, new UserInfo(){ ID = 2, UserName = "李四", UserCompanyID = 1 }, new UserInfo(){ ID = 3, UserName = "王五", UserCompanyID = 4 }, new UserInfo(){ ID = 4, UserName = "赵六", UserCompanyID = 1 }, new UserInfo(){ ID = 5, UserName = "杨七", UserCompanyID = 3 }, new UserInfo(){ ID = 6, UserName = "朱八", UserCompanyID = 1 }, new UserInfo(){ ID = 7, UserName = "孙九", UserCompanyID = 2 }, new UserInfo(){ ID = 8, UserName = "萧十一郎", UserCompanyID = 1 } }; } /// <summary> /// 得到所有的公司信息 /// </summary> /// <returns></returns> static IList<UserCompany> GetAllUserCompanys() { return new List<UserCompany>() { new UserCompany(){ ID = 1, CompanyName = "新浪", CompanyDesc = "新浪是个大公司" }, new UserCompany(){ ID = 2, CompanyName = "百度", CompanyDesc = "百度是个大公司" }, new UserCompany(){ ID = 3, CompanyName = "腾讯", CompanyDesc = "腾讯是个大公司" }, new UserCompany(){ ID = 4, CompanyName = "网易", CompanyDesc = "网易是个大公司" }, new UserCompany(){ ID = 5, CompanyName = "搜狐", CompanyDesc = "搜狐是个大公司" }, new UserCompany(){ ID = 6, CompanyName = "阿里巴巴", CompanyDesc = "阿里巴巴是个大公司" } }; } /// <summary> /// 根据一个或多个 CompanyId 得到公司。 /// </summary> /// <param name="companyIds">一个或多个 CompanyId</param> /// <returns></returns> static IEnumerable<UserCompany> GetCompanysByCompanyIds(IEnumerable<int> companyIds) { IList<UserCompany> companys = GetAllUserCompanys(); foreach (int companyId in companyIds) { yield return companys.FirstOrDefault(c => c.ID == companyId); } } } }
运行结果截图:
如果我们要让这些员工类(UserInfo)的实体属性 UserCompany_UserCompanyID 自动指向已经被加载出来的公司实体,怎么办呢?下面有一种方法(完整代码):
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConAppTest { class Program { static void Main(string[] args) { IList<UserInfo> users = GetAllUserInfos(); IEnumerable<int> userCompanyIds = users.Select<UserInfo, int>(u => u.UserCompanyID).Distinct(); IEnumerable<UserCompany> existsCompanys = GetCompanysByCompanyIds(userCompanyIds); foreach (UserCompany companyItem in existsCompanys) { if(companyItem == null) { continue; } Console.WriteLine(companyItem.CompanyName); } // 把一个实体类作为属性的引用指向另一个实体类 foreach (UserInfo userItem in users) { foreach (UserCompany companyItem in existsCompanys) { if (userItem.UserCompanyID == companyItem.ID) { userItem.UserCompany_UserCompanyID = companyItem; break; } } } // 下面是打印出信息 foreach (UserInfo userItem in users) { Console.WriteLine("姓名:" + userItem.UserName + ",公司:" + userItem.UserCompany_UserCompanyID.CompanyName); } } /// <summary> /// 得到所有的员工信息 /// </summary> /// <returns></returns> static IList<UserInfo> GetAllUserInfos() { return new List<UserInfo>() { new UserInfo(){ ID = 1, UserName = "张三", UserCompanyID = 2 }, new UserInfo(){ ID = 2, UserName = "李四", UserCompanyID = 1 }, new UserInfo(){ ID = 3, UserName = "王五", UserCompanyID = 4 }, new UserInfo(){ ID = 4, UserName = "赵六", UserCompanyID = 1 }, new UserInfo(){ ID = 5, UserName = "杨七", UserCompanyID = 3 }, new UserInfo(){ ID = 6, UserName = "朱八", UserCompanyID = 1 }, new UserInfo(){ ID = 7, UserName = "孙九", UserCompanyID = 2 }, new UserInfo(){ ID = 8, UserName = "萧十一郎", UserCompanyID = 1 } }; } /// <summary> /// 得到所有的公司信息 /// </summary> /// <returns></returns> static IList<UserCompany> GetAllUserCompanys() { return new List<UserCompany>() { new UserCompany(){ ID = 1, CompanyName = "新浪", CompanyDesc = "新浪是个大公司" }, new UserCompany(){ ID = 2, CompanyName = "百度", CompanyDesc = "百度是个大公司" }, new UserCompany(){ ID = 3, CompanyName = "腾讯", CompanyDesc = "腾讯是个大公司" }, new UserCompany(){ ID = 4, CompanyName = "网易", CompanyDesc = "网易是个大公司" }, new UserCompany(){ ID = 5, CompanyName = "搜狐", CompanyDesc = "搜狐是个大公司" }, new UserCompany(){ ID = 6, CompanyName = "阿里巴巴", CompanyDesc = "阿里巴巴是个大公司" } }; } /// <summary> /// 根据一个或多个 CompanyId 得到公司。 /// </summary> /// <param name="companyIds">一个或多个 CompanyId</param> /// <returns></returns> static IEnumerable<UserCompany> GetCompanysByCompanyIds(IEnumerable<int> companyIds) { IList<UserCompany> companys = GetAllUserCompanys(); foreach (int companyId in companyIds) { yield return companys.FirstOrDefault(c => c.ID == companyId); } } } class UserCompany { public int ID { get; set; } public string CompanyName { get; set; } public string CompanyDesc { get; set; } } class UserInfo { public int ID { get; set; } public string UserName { get; set; } public int UserCompanyID { get; set; } public UserCompany UserCompany_UserCompanyID { get; set; } } }
运行结果截图:
不知道大家注意下面这段代码没有:
foreach (UserInfo userItem in users) { foreach (UserCompany companyItem in existsCompanys) { if (userItem.UserCompanyID == companyItem.ID) { userItem.UserCompany_UserCompanyID = companyItem; break; } } }
如果我们的很多地方都要实现“把一个实体类作为属性的引用指向另一个实体类”,怎么办呢?难道也是 2 层循环,先判断 ID 是否相等,然后赋值吗?
我不喜欢写重复的代码,于是想到了委托来简化。下面是代码:
/// <summary> /// 让指针指向一个实体 /// </summary> /// <typeparam name="TSource">源实体集合</typeparam> /// <typeparam name="TValue">值实体集合</typeparam> /// <param name="sourceItems">源实体集合</param> /// <param name="sourceValueItems">值实体集合</param> /// <param name="fn">判断 true or false 的委托</param> /// <param name="actionEvaluate">做一个什么事的委托</param> static void LetPointerEvaluateEntity<TSource, TValue>(IEnumerable<TSource> sourceItems, IEnumerable<TValue> sourceValueItems, Func<TSource, TValue, bool> fn, Action<TSource, TValue> actionEvaluate) { foreach (var sourceItem in sourceItems) { foreach (var valueItem in sourceValueItems) { if (fn(sourceItem, valueItem)) { //做一些事,比如:赋值(把一个对象的属性指向另一个对象) actionEvaluate(sourceItem, valueItem); break; } } } }
最后在客户端调用就可以了。完整代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConAppTest { class Program { static void Main(string[] args) { IList<UserInfo> users = GetAllUserInfos(); IEnumerable<int> userCompanyIds = users.Select<UserInfo, int>(u => u.UserCompanyID).Distinct(); IEnumerable<UserCompany> existsCompanys = GetCompanysByCompanyIds(userCompanyIds); foreach (UserCompany companyItem in existsCompanys) { if(companyItem == null) { continue; } Console.WriteLine(companyItem.CompanyName); } // 把一个实体类作为属性的引用指向另一个实体类 /* foreach (UserInfo userItem in users) { foreach (UserCompany companyItem in existsCompanys) { if (userItem.UserCompanyID == companyItem.ID) { userItem.UserCompany_UserCompanyID = companyItem; break; } } } */ // 把一个实体类作为属性的引用指向另一个实体类(用委托来简化后) LetPointerEvaluateEntity<UserInfo, UserCompany>(users, existsCompanys, (user, userCompany) => user.UserCompanyID == userCompany.ID, (user, userCompany) => user.UserCompany_UserCompanyID = userCompany); // 下面是打印出信息 foreach (UserInfo userItem in users) { Console.WriteLine("姓名:" + userItem.UserName + ",公司:" + userItem.UserCompany_UserCompanyID.CompanyName); } } /// <summary> /// 得到所有的员工信息 /// </summary> /// <returns></returns> static IList<UserInfo> GetAllUserInfos() { return new List<UserInfo>() { new UserInfo(){ ID = 1, UserName = "张三", UserCompanyID = 2 }, new UserInfo(){ ID = 2, UserName = "李四", UserCompanyID = 1 }, new UserInfo(){ ID = 3, UserName = "王五", UserCompanyID = 4 }, new UserInfo(){ ID = 4, UserName = "赵六", UserCompanyID = 1 }, new UserInfo(){ ID = 5, UserName = "杨七", UserCompanyID = 3 }, new UserInfo(){ ID = 6, UserName = "朱八", UserCompanyID = 1 }, new UserInfo(){ ID = 7, UserName = "孙九", UserCompanyID = 2 }, new UserInfo(){ ID = 8, UserName = "萧十一郎", UserCompanyID = 1 } }; } /// <summary> /// 得到所有的公司信息 /// </summary> /// <returns></returns> static IList<UserCompany> GetAllUserCompanys() { return new List<UserCompany>() { new UserCompany(){ ID = 1, CompanyName = "新浪", CompanyDesc = "新浪是个大公司" }, new UserCompany(){ ID = 2, CompanyName = "百度", CompanyDesc = "百度是个大公司" }, new UserCompany(){ ID = 3, CompanyName = "腾讯", CompanyDesc = "腾讯是个大公司" }, new UserCompany(){ ID = 4, CompanyName = "网易", CompanyDesc = "网易是个大公司" }, new UserCompany(){ ID = 5, CompanyName = "搜狐", CompanyDesc = "搜狐是个大公司" }, new UserCompany(){ ID = 6, CompanyName = "阿里巴巴", CompanyDesc = "阿里巴巴是个大公司" } }; } /// <summary> /// 根据一个或多个 CompanyId 得到公司。 /// </summary> /// <param name="companyIds">一个或多个 CompanyId</param> /// <returns></returns> static IEnumerable<UserCompany> GetCompanysByCompanyIds(IEnumerable<int> companyIds) { IList<UserCompany> companys = GetAllUserCompanys(); foreach (int companyId in companyIds) { yield return companys.FirstOrDefault(c => c.ID == companyId); } } /// <summary> /// 让指针指向一个实体 /// </summary> /// <typeparam name="TSource">源实体集合</typeparam> /// <typeparam name="TValue">值实体集合</typeparam> /// <param name="sourceItems">源实体集合</param> /// <param name="sourceValueItems">值实体集合</param> /// <param name="fn">判断 true or false 的委托</param> /// <param name="actionEvaluate">做一个什么事的委托</param> static void LetPointerEvaluateEntity<TSource, TValue>(IEnumerable<TSource> sourceItems, IEnumerable<TValue> sourceValueItems, Func<TSource, TValue, bool> fn, Action<TSource, TValue> actionEvaluate) { foreach (var sourceItem in sourceItems) { foreach (var valueItem in sourceValueItems) { if (fn(sourceItem, valueItem)) { //做一些事,比如:赋值(把一个对象的属性指向另一个对象) actionEvaluate(sourceItem, valueItem); break; } } } } } class UserCompany { public int ID { get; set; } public string CompanyName { get; set; } public string CompanyDesc { get; set; } } class UserInfo { public int ID { get; set; } public string UserName { get; set; } public int UserCompanyID { get; set; } public UserCompany UserCompany_UserCompanyID { get; set; } } }
运行结果和上面的代码一样,这个方法让代码简化了很多,是不是呢?您有什么不同的观点,请分享!下面是截图:
呵呵,这是我第一次发首页,谢谢你来捧场,也许你可能觉得这代码太简单了,不值得发首页。但无论如何,和大家分享自己的一点技术应该没有错吧,
也许还是可能帮助其他人提高一点点,谢谢!
作者:音乐让我说(音乐让我说 - 博客园)
出处:http://music.cnblogs.com/
文章版权归本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。