首页 > 作文

C#内置泛型委托之Func委托

更新时间:2023-04-06 03:36:12 阅读: 评论:0

一、什么是func委托

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

二、func委托定义

查看func的定义:

using system.runtime.compilerrvices;namespace system{    //    // 摘要:    //     封装一个方法,该方法具有两个参数,并返回由 tresult 参数指定的类型的值。    //    // 参数:    //   arg1:    //     此委托封装的方法的第一个参数。    //    //   arg2:    //     此委托封装的方法的第二个参数。    //    // 类型参数:    //   t1:    //     此委托封装的方法的第一个参数的类型。    //    //   t2:    //     此委托封装的方法的第二个参数的类型。    //    //   tresult:    //     此委托封装的方法的返回值类型。    //    // 返回结果:    //     此委托封装的方法的返回值。    [typeforwardedfrom("system.core, version=3.5.0.0, culture=neutral, publickeytoken=b77a5c561934e089")]    public delegate tresult func<in t1, in t2, out tresult>(t1 arg1, t2 arg2);}

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

3、示例

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

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

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

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

func<t1,t2,,t3,int> 表示传入参数为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<int> fun1 = new func<int>(funwithnopara);            int result1= fun1();            console.writeline(result1);            console.writeline("----------------------------");            func<int> fun2 = delegate { return 19; };            int result2 = fun2();            console.writeline(result2);            console.writeline("----------------------------");            func<int> fun3 = () => { return 3; };            int result3 = fun3();            console.writeline(result3);            console.writeline("----------------------------");            //有一个参数,一个返回值            func<int, int> fun4 = new func<int, int>(funwithpara);            int result4 = fun4(4);            console.writeline($"这里是一个参数一个返回值的方法,返回值是:{result4}");            console.writeline("----------------------------");            // 使用委托            func<int, string> fun5 = delegate (int i) { return i.tostring(); };            string result5 = fun5(5);            console.writeline($"这里是一个参数一个返回值的委托,返回值是:{result5}");            console.writeline("----------------------------");            // 使用匿名委托            func<int, string> fun6 = (int i) =>             {                return i.tostring();            };            string result6 = fun6(6);            console.writeline($"这里是一个参数一个返回值的匿名委托,返回值是:{result6}");            console.writeline("----------------------------");            // 多个输入参数            func<int, string, bool> fun7 = new func<int, string, bool>(funwithmultipara);            bool result7 = fun7(2, "2");            console.writeline($"这里是有多个输入参数的方法,返回值是:{result7}");            console.writeline("----------------------------");            // 使用委托            func<int, string, bool> fun8 = delegate (int i, string s)             {                return i.tostring().equals(s) ? true : fal;            };            bool result8 = fun8(2, "abc");            console.writeline($"这里是有多个输入参数的委托,返回值是:{result8}");            console.writeline("----------------------------");            // 使用匿名委托            func<int, string, bool> fun9 = (int i, string s) =>             {                return i.tostring().equals(s) ? true : fal;            };            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 : fal;        }    }}

运行结果:

4、真实示例

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

1、定义bamodel基类

using system;using system.collections.generic;using system.linq;using system.text;using system.threading.tasks;namespace funapplication.model{    public class bamodel    {        public int id { get; t; }    }}

2、定义student类继承自bamodel基类

using system;using system.collections.generic;using system.linq;using system.text;using system.threading.tasks;namespace funapplication.model{    public class student : bamodel    {        public string name { get; t; }        public int age { get; t; }        public int x { get; t; }        public string email { get; t; }    }}

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 ibadal    {        t query<t>(int id) where t : bamodel;        list<t> queryall<t>() where t : bamodel;        int inrt<t>(t t) where t : bamodel;        int update<t>(t t) where t : bamodel;        int delete<t>(int id) where t : bamodel;    }}

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();            }            el            {                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 badal : ibadal    {        // 数据库链接字符串        private static string strconn = configurationmanager.connectionstrings["dbconnection"].connectionstring;        public  int delete<t>(int id) where t : bamodel        {            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 inrt<t>(t t) where t : bamodel        {            int result = 0;            using (sqlconnection conn = new sqlconnection(strconn))            {                type type = typeof(t);                var proparray = type.getproperties().where(p => p.name != "id");                string strsql = "inrt into student values (@name,@age,@x,@email) ";                sqlcommand command = new sqlcommand(strsql, conn);                var parameters = proparray.lect(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<t>(int id) where t : bamodel        {            type type = typeof(t);            string columnstring = string.join(",", type.getproperties().lect(p => $"[{p.getcolumnname()}]"));            string sql = $"lect {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<t> list = this.readertolist<t>(reader);                t = list.firstordefault();                      }            return t;        }        public list<t> queryall<t>() where t : bamodel        {            type type = typeof(t);            string columnstring = string.join(",", type.getproperties().lect(p => $"[{p.getcolumnname()}]"));            string sql = $"lect {columnstring} from [{type.name}] ";            list<t> list = new list<t>();            using (sqlconnection conn = new sqlconnection(strconn))            {                sqlcommand command = new sqlcommand(sql, conn);                conn.open();                sqldatareader reader = command.executereader();                list = this.readertolist<t>(reader);            }            return list;        }        public int update<t>(t t) where t : bamodel        {            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.lect(p => $"[{p.getcolumnname()}]=@{p.getcolumnname()}"));                var parameters = proparray.lect(p => new sqlparameter($"@{p.getcolumnname()}", p.getvalue(t) ?? dbnull.value)).toarray();                                //必须参数化  否则引号?  或者值里面还有引号                string strsql = $"update [{type.name}] t {columnstring} where id={t.id}";                sqlcommand command = new sqlcommand(strsql, conn);                command.parameters.addrange(parameters);                conn.open();                result = command.executenonquery();                        }            return result;        }        private list<t> readertolist<t>(sqldatareader reader) where t : bamodel        {            type type = typeof(t);            list<t> list = new list<t>();            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.tvalue(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            badal dal = new badal();            // 查询            student student = dal.query<student>(2);            console.writeline($"姓名:{student.name},年龄:{student.age},email地址:{student.email}");            console.writeline("----------------------------");            // 查询所有            list<student> list = dal.queryall<student>();            console.writeline($"集合个数:{list.count}");            console.writeline("----------------------------");            // 插入            student studentins = new student()            {                name = "小明",                age = 20,                x = 2,                email = "xiaoming@qq.com"            };            bool resultins = dal.inrt<student>(studentins) > 0 ? true : fal;            console.writeline($"插入执行结果:{resultins}");            console备课大师语文.writeline("----------------------------");            // 更新            student studentupd = new student()            {                id = 1,                name = "zhangsan1234",                age = 20,                x = 2,                email = "zhangsan1234@qq.com"            };            bool resultupd = dal.update<student>(studentupd) > 0 ? true : fal;            console.writeline($"更新执行结果:{resultupd}");            console.writeline("----------------------------");            // 删除            bool resultdel = dal.delete<student>(3) > 0 ? true : fal;            console.writeline($"删除执行结果:{resultdel}");            #endregion            console.readkey();        }    }}

8、结果

寻找qq网名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 funbadal : ibadal    {        // 数据库链接字符串        private static string strconn = configurationmanager.connectionstrings["dbconnection"].connectionstring;        public int delete<t>(int id) where t : bamodel        {            type type = typeof(t);            string sql = $"delete from {type.name} where id=@id";            func<sqlcommand, int> func = (sqlcommand command) =>             {                               sqlparameter para = new sqlparameter("id", id);                command.parameters.add(para);                return command.executenonquery();            };            return excutesql<int>(sql, func);        }        public int inrt<t>(t t) where t : bamodel        {            int result = 0;            type type = typeof(t);            var proparray = type.getproperties().where(p => p.name != "id");            string strsql = "inrt into student values (@name,@age,@x,@email) ";            var parameters = proparray.lect(p => new sqlparameter($"@{p.getcolumnname()}", p.getvalue(t) ?? dbnull.value)).toarray();            func<sqlcommand, int> func = (sqlcommand command) =>             {                command.parameters.addrange(parameters);                return command.executenonquery();            };            result = excutesql<int>(strsql, func);            return result;        }        public t query<t>(int id) where t : bamodel        {            type type = typeof(t);            string columnstring = string.join(",", type.getproperties().lect(p => $"[{p.getcolumnname()}]"));            string sql = $"lect {columnstring} from [{type.name}] where id=@id";            t t = null;            datatable dt = new datatable();                        func<sqlcommand, t> func = (sqlcommand command) =>             {                sqlparameter para = new sqlparameter("@id", id);                command.parameters.add(para);                sqldataadapter adapter = new sqldataadapter(command);                //sqldatareader reader = command.executereader();                //list<t> list = this.readertolist<t>(reader);                adapter.fill(dt);                list<t> list = converttolist<t>(dt);                t tresult = list.firstordefault();                return tresult;            };            t = excutesql<t>(sql, func);            return t;        }        public list<t> queryall<t>() where t : bamodel        {            type type = typeof(t);            string columnstring = string.join(",", type.getproperties().lect(p => $"[{p.getcolumnname()}]"));            string sql = $"lect {columnstring} from [{type.name}] ";            t t = null;            func<sqlcommand, list<t>> func = (sqlcommand command) =>            {                sqldatareader reader = command.executereader();                list<t> list = this.readertolist<t>(reader);                return list;            };            return excutesql<list<t>>(sql, func);        }        public int update<t>(t t) where t : bamodel        {            int result = 0;            type type = typeof(t);            var proparray = type.getproperties().where(p => p.name != "id");            string columnstring = string.join(",", proparray.lect(p => $"[{p.getcolumnname()}]=@{p.getcolumnname()}"));            var parameters = proparray.lect(p => new sqlparameter($"@{p.getcolumnname()}", p.getvalue(t) ?? dbnull.value)).toarray();            //必须参数化  否则引号?  或者值里面还有引号            string strsql = $"update [{type.name}] t {columnstring} where id={t.id}";            func<sqlcommand, int> func = (sqlcommand command) =>             {                command.parameters.addrange(parameters);                return command.executenonquery();            };            result = excutesql<int>(strsql, func);            return result;        }        //多个方法里面重复对数据库的访问  想通过委托解耦,去掉重复代码        private t excutesql<t>(string sql, func<sqlcommand, t> 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<t> readertolist<t>(sqldatareader reader) where t : bamodel        {            type type = typeof(t);            list<t> list = new list<t>();            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.tvalue(t, ovalue);//除了guid和枚举                }                list.add(t);            }            reader.clo();            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 传统实现            //badal dal = new badal();            //// 查询            //student student = dal.query<student>(2);            //console.writeline($"姓名:{student.name},年龄:{student.age},email地址:{student.email}");            //console.writeline("----------------------------");            //// 查询所有            //list<student> list = dal.queryall<student>();            //console.writeline($"集合个数:{list.count}");            //console.writeline("----------------------------");            //// 插入            //student studentins = new student()            //{            //    name = "小明",            //    age = 20,            //    x = 2,            //    email = "xiaoming@qq.com"            //};            //bool resultins = dal.inrt<student>(studentins) > 0 ? true : fal;            //console.writeline($"插入执行结果:{resultins}");            //console.writeline("----------------------------");            //// 更新            //student studentupd = new student()            //{            //    id = 1,            //    name = "zhangsan1234",            //    age = 20,            //    x = 2,            //    email = "zhangsan1234@qq.com"            //};            //bool resultupd = dal.update<student>(studentupd) > 1 ? true : fal;            //console.writeline($"更新执行结果:{resultupd}");            //console.writeline("----------------------------");            //// 删除            //bool resultdel = dal.delete<student>(5) > 1 ? true : fal;            //console.writeline($"删除执行结果:{resultdel}");            #endregion            #region 利用委托            // 查询            funbadal dal = new funbadal();            student student = dal.query<student>(1);            console.writeline($"姓名:{student.name},年龄:{student.age},email地址:{student.email}");            console.writeline("----------------------------");            // 查询所有            list<student> list = dal.queryall<student>();            console.writeline($"集合个数:{list.count}");            console.writeline("----------------------------");            // 插入            student studentins = new student()            {                name = "tom",                age = 19,                x = 1,                email = "tom@163.com"            };            bool resultins = dal.inrt<student>(studentins) > 0 ? true : fal;            console.writeline($"插入执行结果:{resultins}");            console.writeline("----------------------------");            list<student> list1 = dal.queryall<student>();            console.writeline($"插入后集合个数:{list1.count}");            console.writeline("----------------------------");            // 更新            student studentupd = new student()            {                id = 2,                name = "马六123",                age = 20,                x = 2,                email = "maliu1234@qq.com"            };            bool resultupd = dal.update<student>(studentupd) > 0 ? true : fal;            console.writeline($"更新执行结果:{resultupd}");            console.writeline("----------------------------");            // 删除            bool resultdel = dal.delete<student>(8) > 0 ? true : fal;            console.writeline($"删除执行结果:{resultdel}");            list<student> list2 = dal.queryall<student>();            console.writeline($"删除后集合个数:{list2.count}");            console.writeline("----------------------------");            #endregion            console.readkey();        }    }}

11、结果

注意

在使用sqldatareader的时候有时会报错:“已有打开的与此command相关联的datareader,必须先将它关闭”。

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

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

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

<?xml version="1.0" encoding="utf-8" ?><configuration>  <connectionstrings>    <!--<add name="dbconnection" connectionstring="rver=.;initial catalog=mydb;ur id=sa;password=123456;multipleactiveresultts=true"/>-->    <!--配置文件里面添加multipleactiveresultts=true-->    <add name="dbconnection" connectionstring="rver=.;initial catalog=mydb;ur id=sa;password=123456;multipleactiveresultts=true"/>  </connectionstrings别日克>    <startup>         <supportedruntime version="v4.0" sku=".netframework,version=v4.6.1" />    </startup></configuration>

2、使用datatable

在上面是使用的sqldatareader读取数据,然后转换成list<t>,可以用datatable代替sqldatareader,这样就不会报错了,代码如下:

/// <summary>/// 将datatable转换成list/// </summary>/// <typeparam name="t"></typeparam>/// <param name="dt"></param>/// <returns></returns>private list<t> converttolist<t>(datatable dt) where t:bamodel{      type type = typeof(t);      list<t> list = new list<t>();      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.tvalue(t, value);          }          list.add(t);        }        return list;}

到此这篇关于c#内置泛型委托之func委托的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持www.887551.com。

本文发布于:2023-04-06 03:36:10,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/ac627bd2c2c0fde7bdb6df332dbcfe54.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:C#内置泛型委托之Func委托.doc

本文 PDF 下载地址:C#内置泛型委托之Func委托.pdf

标签:参数   返回值   方法   多个
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图