代码改变世界

让 C# 委托来帮你简化代码,学习使用 Func、Action 委托

2011-10-03 16:28  音乐让我说  阅读(4313)  评论(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; }
    }
}

  

运行结果和上面的代码一样,这个方法让代码简化了很多,是不是呢?您有什么不同的观点,请分享!下面是截图:

呵呵,这是我第一次发首页,谢谢你来捧场,也许你可能觉得这代码太简单了,不值得发首页。但无论如何,和大家分享自己的一点技术应该没有错吧,
也许还是可能帮助其他人提高一点点,谢谢!

代码下载:https://files.cnblogs.com/Music/DelegateDemo.rar