千家信息网

C#的Func委托怎么实现

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇内容介绍了"C#的Func委托怎么实现"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、什么是F
千家信息网最后更新 2026年11月01日C#的Func委托怎么实现

本篇内容介绍了"C#的Func委托怎么实现"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

一、什么是Func委托

Func委托代表有返回类型的委托

二、Func委托定义

查看Func的定义:

using System.Runtime.CompilerServices;namespace System{    //    // 摘要:    //     封装一个方法,该方法具有两个参数,并返回由 TResult 参数指定的类型的值。    //    // 参数:    //   arg1:    //     此委托封装的方法的第一个参数。    //    //   arg2:    //     此委托封装的方法的第二个参数。    //    // 类型参数:    //   T1:    //     此委托封装的方法的第一个参数的类型。    //    //   T2:    //     此委托封装的方法的第二个参数的类型。    //    //   TResult:    //     此委托封装的方法的返回值类型。    //    // 返回结果:    //     此委托封装的方法的返回值。    [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]    public delegate TResult Func(T1 arg1, T2 arg2);}

你会发现,Func其实就是有多个输出参数并且有返回值的delegate。

3、示例

Func至少0个输入参数,至多16个输入参数,根据返回值泛型返回。必须有返回值,不可void。

Func 表示没有输入参参,返回值为int类型的委托。

Func 表示传入参数为object, string ,返回值为int类型的委托。

Func 表示传入参数为object, string, 返回值为int类型的委托。

Func 表示传入参数为T1,T2,,T3(泛型),返回值为int类型的委托。

代码示例如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace FunDemo{    class Program    {        static void Main(string[] args)        {            // 无参数,只要返回值             Func fun1 = new Func(FunWithNoPara);            int result1= fun1();            Console.WriteLine(result1);            Console.WriteLine("----------------------------");            Func fun2 = delegate { return 19; };            int result2 = fun2();            Console.WriteLine(result2);            Console.WriteLine("----------------------------");            Func fun3 = () => { return 3; };            int result3 = fun3();            Console.WriteLine(result3);            Console.WriteLine("----------------------------");            //有一个参数,一个返回值            Func fun4 = new Func(FunWithPara);            int result4 = fun4(4);            Console.WriteLine($"这里是一个参数一个返回值的方法,返回值是:{result4}");            Console.WriteLine("----------------------------");            // 使用委托            Func fun5 = delegate (int i) { return i.ToString(); };            string result5 = fun5(5);            Console.WriteLine($"这里是一个参数一个返回值的委托,返回值是:{result5}");            Console.WriteLine("----------------------------");            // 使用匿名委托            Func fun6 = (int i) =>             {                return i.ToString();            };            string result6 = fun6(6);            Console.WriteLine($"这里是一个参数一个返回值的匿名委托,返回值是:{result6}");            Console.WriteLine("----------------------------");            // 多个输入参数            Func fun7 = new Func(FunWithMultiPara);            bool result7 = fun7(2, "2");            Console.WriteLine($"这里是有多个输入参数的方法,返回值是:{result7}");            Console.WriteLine("----------------------------");            // 使用委托            Func fun8 = delegate (int i, string s)             {                return i.ToString().Equals(s) ? true : false;            };            bool result8 = fun8(2, "abc");            Console.WriteLine($"这里是有多个输入参数的委托,返回值是:{result8}");            Console.WriteLine("----------------------------");            // 使用匿名委托            Func fun9 = (int i, string s) =>             {                return i.ToString().Equals(s) ? true : false;            };            bool result9 = fun9(45, "ert");            Console.WriteLine($"这里是有多个输入参数的匿名委托,返回值是:{result9}");            Console.ReadKey();        }        static int FunWithNoPara()        {            return 10;        }        static int FunWithPara(int i)        {            return i;        }        static bool FunWithMultiPara(int i,string s)        {            return i.ToString().Equals(s) ? true : false;        }    }}

运行结果:

4、真实示例

在下面的示例中,利用Func委托封装数据库通用访问类。

1、定义BaseModel基类

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace FunApplication.Model{    public class BaseModel    {        public int Id { get; set; }    }}

2、定义Student类继承自BaseModel基类

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace FunApplication.Model{    public class Student : BaseModel    {        public string Name { get; set; }        public int Age { get; set; }        public int Sex { get; set; }        public string Email { get; set; }    }}

3、定义数据库访问方法接口

using FunApplication.Model;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace FunApplication.IDAL{    public interface IBaseDAL    {        T Query(int id) where T : BaseModel;        List QueryAll() where T : BaseModel;        int Insert(T t) where T : BaseModel;        int Update(T t) where T : BaseModel;        int Delete(int id) where T : BaseModel;    }}

4、定义属性帮助类

using System;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.Text;using System.Threading.Tasks;namespace FunApplication.AttributeExtend{    public static class AttributeHelper    {        public static string GetColumnName(this PropertyInfo prop)        {            if (prop.IsDefined(typeof(ColumnAttribute), true))            {                ColumnAttribute attribute = (ColumnAttribute)prop.GetCustomAttribute(typeof(ColumnAttribute), true);                return attribute.GetColumnName();            }            else            {                return prop.Name;            }        }    }}

5、定义ColumnAttribute类

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace FunApplication.AttributeExtend{    [AttributeUsage(AttributeTargets.Property)]    public class ColumnAttribute : Attribute    {        public ColumnAttribute(string name)        {            this._Name = name;        }        private string _Name = null;        public string GetColumnName()        {            return this._Name;        }    }}

6、定义数据库方法接口实现类

using FunApplication.IDAL;using FunApplication.Model;using System;using System.Collections.Generic;using System.Configuration;using System.Data.SqlClient;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Reflection;using FunApplication.AttributeExtend;namespace FunApplication.DAL{    public  class BaseDAL : IBaseDAL    {        // 数据库链接字符串        private static string strConn = ConfigurationManager.ConnectionStrings["DbConnection"].ConnectionString;        public  int Delete(int id) where T : BaseModel        {            int result = 0;            using (SqlConnection conn = new SqlConnection(strConn))            {                string strSQL = "delete from Student where Id=@Id";                SqlParameter para = new SqlParameter("Id", id);                SqlCommand command = new SqlCommand(strSQL, conn);                command.Parameters.Add(para);                conn.Open();                result = command.ExecuteNonQuery();            }            return result;        }        public int Insert(T t) where T : BaseModel        {            int result = 0;            using (SqlConnection conn = new SqlConnection(strConn))            {                Type type = typeof(T);                var propArray = type.GetProperties().Where(p => p.Name != "Id");                string strSQL = "insert into Student Values (@Name,@Age,@Sex,@Email) ";                SqlCommand command = new SqlCommand(strSQL, conn);                var parameters = propArray.Select(p => new SqlParameter($"@{p.GetColumnName()}", p.GetValue(t) ?? DBNull.Value)).ToArray();                command.Parameters.AddRange(parameters);                conn.Open();                result = command.ExecuteNonQuery();            }                return result;        }        public T Query(int id) where T : BaseModel        {            Type type = typeof(T);            string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));            string sql = $"SELECT {columnString} FROM [{type.Name}] WHERE Id={id}";            T t = null;// (T)Activator.CreateInstance(type);            using (SqlConnection conn = new SqlConnection(strConn))            {                SqlCommand command = new SqlCommand(sql, conn);                conn.Open();                SqlDataReader reader = command.ExecuteReader();                List list = this.ReaderToList(reader);                t = list.FirstOrDefault();                      }            return t;        }        public List QueryAll() where T : BaseModel        {            Type type = typeof(T);            string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));            string sql = $"SELECT {columnString} FROM [{type.Name}] ";            List list = new List();            using (SqlConnection conn = new SqlConnection(strConn))            {                SqlCommand command = new SqlCommand(sql, conn);                conn.Open();                SqlDataReader reader = command.ExecuteReader();                list = this.ReaderToList(reader);            }            return list;        }        public int Update(T t) where T : BaseModel        {            int result = 0;            using (SqlConnection conn = new SqlConnection(strConn))            {                Type type = typeof(T);                var propArray = type.GetProperties().Where(p => p.Name != "Id");                string columnString = string.Join(",", propArray.Select(p => $"[{p.GetColumnName()}]=@{p.GetColumnName()}"));                var parameters = propArray.Select(p => new SqlParameter($"@{p.GetColumnName()}", p.GetValue(t) ?? DBNull.Value)).ToArray();                                //必须参数化  否则引号?  或者值里面还有引号                string strSQL = $"UPDATE [{type.Name}] SET {columnString} WHERE Id={t.Id}";                SqlCommand command = new SqlCommand(strSQL, conn);                command.Parameters.AddRange(parameters);                conn.Open();                result = command.ExecuteNonQuery();                        }            return result;        }        private List ReaderToList(SqlDataReader reader) where T : BaseModel        {            Type type = typeof(T);            List list = new List();            while (reader.Read())//表示有数据  开始读            {                T t = (T)Activator.CreateInstance(type);                foreach (var prop in type.GetProperties())                {                    object oValue = reader[prop.GetColumnName()];                    if (oValue is DBNull)                        oValue = null;                    prop.SetValue(t, oValue);//除了guid和枚举                }                list.Add(t);            }            return list;        }    }}

7、在Main()方法中调用

using FunApplication.DAL;using FunApplication.Model;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace FunApplication{    class Program    {        static void Main(string[] args)        {            #region MyRegion            BaseDAL dal = new BaseDAL();            // 查询            Student student = dal.Query(2);            Console.WriteLine($"姓名:{student.Name},年龄:{student.Age},Email地址:{student.Email}");            Console.WriteLine("----------------------------");            // 查询所有            List list = dal.QueryAll();            Console.WriteLine($"集合个数:{list.Count}");            Console.WriteLine("----------------------------");            // 插入            Student studentIns = new Student()            {                Name = "小明",                Age = 20,                Sex = 2,                Email = "xiaoming@qq.com"            };            bool resultIns = dal.Insert(studentIns) > 0 ? true : false;            Console.WriteLine($"插入执行结果:{resultIns}");            Console.WriteLine("----------------------------");            // 更新            Student studentUpd = new Student()            {                Id = 1,                Name = "zhangsan1234",                Age = 20,                Sex = 2,                Email = "zhangsan1234@qq.com"            };            bool resultUpd = dal.Update(studentUpd) > 0 ? true : false;            Console.WriteLine($"更新执行结果:{resultUpd}");            Console.WriteLine("----------------------------");            // 删除            bool resultDel = dal.Delete(3) > 0 ? true : false;            Console.WriteLine($"删除执行结果:{resultDel}");            #endregion            Console.ReadKey();        }    }}

8、结果

9、优化

仔细观察上面步骤7中的代码,你会发现在每个方法中都有重复的代码,打开链接,执行SqlCommand命令,那么这些重复的代码能不能提取到一个公共的方法中进行调用呢?答案是可以的,那就是利用Func委托,看下面优化后的代码:

using FunApplication.AttributeExtend;using FunApplication.IDAL;using FunApplication.Model;using System;using System.Collections.Generic;using System.Configuration;using System.Data;using System.Data.SqlClient;using System.Linq;using System.Reflection;using System.Text;using System.Threading.Tasks;namespace FunApplication.DAL{    public class FunBaseDAL : IBaseDAL    {        // 数据库链接字符串        private static string strConn = ConfigurationManager.ConnectionStrings["DbConnection"].ConnectionString;        public int Delete(int id) where T : BaseModel        {            Type type = typeof(T);            string sql = $"delete from {type.Name} where Id=@Id";            Func func = (SqlCommand command) =>             {                               SqlParameter para = new SqlParameter("Id", id);                command.Parameters.Add(para);                return command.ExecuteNonQuery();            };            return ExcuteSql(sql, func);        }        public int Insert(T t) where T : BaseModel        {            int result = 0;            Type type = typeof(T);            var propArray = type.GetProperties().Where(p => p.Name != "Id");            string strSQL = "insert into Student Values (@Name,@Age,@Sex,@Email) ";            var parameters = propArray.Select(p => new SqlParameter($"@{p.GetColumnName()}", p.GetValue(t) ?? DBNull.Value)).ToArray();            Func func = (SqlCommand command) =>             {                command.Parameters.AddRange(parameters);                return command.ExecuteNonQuery();            };            result = ExcuteSql(strSQL, func);            return result;        }        public T Query(int id) where T : BaseModel        {            Type type = typeof(T);            string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));            string sql = $"SELECT {columnString} FROM [{type.Name}] WHERE Id=@Id";            T t = null;            DataTable dt = new DataTable();                        Func func = (SqlCommand command) =>             {                SqlParameter para = new SqlParameter("@Id", id);                command.Parameters.Add(para);                SqlDataAdapter adapter = new SqlDataAdapter(command);                //SqlDataReader reader = command.ExecuteReader();                //List list = this.ReaderToList(reader);                adapter.Fill(dt);                List list = ConvertToList(dt);                T tResult = list.FirstOrDefault();                return tResult;            };            t = ExcuteSql(sql, func);            return t;        }        public List QueryAll() where T : BaseModel        {            Type type = typeof(T);            string columnString = string.Join(",", type.GetProperties().Select(p => $"[{p.GetColumnName()}]"));            string sql = $"SELECT {columnString} FROM [{type.Name}] ";            T t = null;            Func> func = (SqlCommand command) =>            {                SqlDataReader reader = command.ExecuteReader();                List list = this.ReaderToList(reader);                return list;            };            return ExcuteSql>(sql, func);        }        public int Update(T t) where T : BaseModel        {            int result = 0;            Type type = typeof(T);            var propArray = type.GetProperties().Where(p => p.Name != "Id");            string columnString = string.Join(",", propArray.Select(p => $"[{p.GetColumnName()}]=@{p.GetColumnName()}"));            var parameters = propArray.Select(p => new SqlParameter($"@{p.GetColumnName()}", p.GetValue(t) ?? DBNull.Value)).ToArray();            //必须参数化  否则引号?  或者值里面还有引号            string strSQL = $"UPDATE [{type.Name}] SET {columnString} WHERE Id={t.Id}";            Func func = (SqlCommand command) =>             {                command.Parameters.AddRange(parameters);                return command.ExecuteNonQuery();            };            result = ExcuteSql(strSQL, func);            return result;        }        //多个方法里面重复对数据库的访问  想通过委托解耦,去掉重复代码        private T ExcuteSql(string sql, Func func)        {            using (SqlConnection conn = new SqlConnection(strConn))            {                using (SqlCommand command = new SqlCommand(sql, conn))                {                    conn.Open();                    SqlTransaction sqlTransaction = conn.BeginTransaction();                    try                    {                        command.Transaction = sqlTransaction;                        T tResult = func.Invoke(command);                        sqlTransaction.Commit();                        return tResult;                    }                    catch (Exception ex)                    {                        sqlTransaction.Rollback();                        throw;                    }                }            }        }        private List ReaderToList(SqlDataReader reader) where T : BaseModel        {            Type type = typeof(T);            List list = new List();            while (reader.Read())//表示有数据  开始读            {                T t = (T)Activator.CreateInstance(type);                foreach (var prop in type.GetProperties())                {                    object oValue = reader[prop.GetColumnName()];                    if (oValue is DBNull)                        oValue = null;                    prop.SetValue(t, oValue);//除了guid和枚举                }                list.Add(t);            }            reader.Close();            return list;        }    }}

10、在Main()方法中调用

using FunApplication.DAL;using FunApplication.Model;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace FunApplication{    class Program    {        static void Main(string[] args)        {            #region 传统实现            //BaseDAL dal = new BaseDAL();            //// 查询            //Student student = dal.Query(2);            //Console.WriteLine($"姓名:{student.Name},年龄:{student.Age},Email地址:{student.Email}");            //Console.WriteLine("----------------------------");            //// 查询所有            //List list = dal.QueryAll();            //Console.WriteLine($"集合个数:{list.Count}");            //Console.WriteLine("----------------------------");            //// 插入            //Student studentIns = new Student()            //{            //    Name = "小明",            //    Age = 20,            //    Sex = 2,            //    Email = "xiaoming@qq.com"            //};            //bool resultIns = dal.Insert(studentIns) > 0 ? true : false;            //Console.WriteLine($"插入执行结果:{resultIns}");            //Console.WriteLine("----------------------------");            //// 更新            //Student studentUpd = new Student()            //{            //    Id = 1,            //    Name = "zhangsan1234",            //    Age = 20,            //    Sex = 2,            //    Email = "zhangsan1234@qq.com"            //};            //bool resultUpd = dal.Update(studentUpd) > 1 ? true : false;            //Console.WriteLine($"更新执行结果:{resultUpd}");            //Console.WriteLine("----------------------------");            //// 删除            //bool resultDel = dal.Delete(5) > 1 ? true : false;            //Console.WriteLine($"删除执行结果:{resultDel}");            #endregion            #region 利用委托            // 查询            FunBaseDAL dal = new FunBaseDAL();            Student student = dal.Query(1);            Console.WriteLine($"姓名:{student.Name},年龄:{student.Age},Email地址:{student.Email}");            Console.WriteLine("----------------------------");            // 查询所有            List list = dal.QueryAll();            Console.WriteLine($"集合个数:{list.Count}");            Console.WriteLine("----------------------------");            // 插入            Student studentIns = new Student()            {                Name = "tom",                Age = 19,                Sex = 1,                Email = "tom@163.com"            };            bool resultIns = dal.Insert(studentIns) > 0 ? true : false;            Console.WriteLine($"插入执行结果:{resultIns}");            Console.WriteLine("----------------------------");            List list1 = dal.QueryAll();            Console.WriteLine($"插入后集合个数:{list1.Count}");            Console.WriteLine("----------------------------");            // 更新            Student studentUpd = new Student()            {                Id = 2,                Name = "马六123",                Age = 20,                Sex = 2,                Email = "maliu1234@qq.com"            };            bool resultUpd = dal.Update(studentUpd) > 0 ? true : false;            Console.WriteLine($"更新执行结果:{resultUpd}");            Console.WriteLine("----------------------------");            // 删除            bool resultDel = dal.Delete(8) > 0 ? true : false;            Console.WriteLine($"删除执行结果:{resultDel}");            List list2 = dal.QueryAll();            Console.WriteLine($"删除后集合个数:{list2.Count}");            Console.WriteLine("----------------------------");            #endregion            Console.ReadKey();        }    }}

11、结果

注意

在使用SqlDataReader的时候有时会报错:"已有打开的与此Command相关联的DataReader,必须先将它关闭"。

同时打开两个或循环多个sqldatareader会出现以上错误。因为用的是sqldatareader做数据库的数据读取,sqlconnection开启没有关闭。

一个SqlConnection只能执行一次事务,没用一次必须关闭然后再开启。上面我只用了一次没有关闭,直接开启所以会报错。解决方案有如下两种:

1、其实不用多次打开在开启,那样实现起来很麻烦。直接在连接字符串的后面加上MultipleActiveResultSets=true即可。 配置文件定义如下:
                                 
2、使用DataTable

在上面是使用的SqlDataReader读取数据,然后转换成List,可以用DataTable代替SqlDataReader,这样就不会报错了,代码如下:

/// /// 将DataTable转换成List/// /// /// /// private List ConvertToList(DataTable dt) where T:BaseModel{      Type type = typeof(T);      List list = new List();      foreach(DataRow dr in dt.Rows)      {          T t = (T)Activator.CreateInstance(type);          foreach(PropertyInfo prop in type.GetProperties())          {               object value = dr[prop.GetColumnName()];               if(value is DBNull)               {                    value = null;               }               prop.SetValue(t, value);          }          list.Add(t);        }        return list;}

"C#的Func委托怎么实现"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

委托 参数 方法 结果 数据 类型 封装 代码 多个 数据库 输入 更新 查询 个数 引号 示例 地址 姓名 字符 字符串 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 百单网互联网科技有限公司 喔噻互联网科技有限公司 广州紫鲸互联网科技有限公司 互联网科技产业 科技金融是不是互联网金融 A股互联网金融科技公司 华宇互联网科技 互联网科技ppt模板 温州喔噻互联网科技有限公司 互联网与医疗科技 996高科技互联网公司 东莞新华互联网科技学校 世界互联网领先科技成果获奖 中科明德北京互联网科技 智帮互联网科技公司最近动向 互联网科技快讯热点 互联网时代科技型公司的机会 互联网公司属于科技吗 互联网领先科技成果宣传视频 宁波允成互联网科技有限公司 上海挚品互联网科技有限公司 互联网金融 科技金融 睿民互联网科技 互联网科技小额贷款 互联网教育科技公司vipkid 创业天下互联网科技有限公司 南通创西澳互联网科技有限公司 深圳无忧互联网科技 艺电能源互联网科技有限公司招聘 承德科技产业互联网平台
0