博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[AaronYang]C#人爱学不学[7]
阅读量:6804 次
发布时间:2019-06-26

本文共 6209 字,大约阅读时间需要 20 分钟。

做一个决定,并不难,难的是付诸行动,并且坚持到底 --Aaronyang的博客(www.ayjs.net)-www.8mi.me

1. 委托-我的总结

 1.1 委托:面试我都会说,把方法当参数。委托包含的只是一个或多个方法的地址。

      示例1:(一次执行多个同方法签名的方法)

/* *2015年1月3日23:12:13 aaronyang *网址:www.ayjs.net       www.8mi.me */using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace demo0103{    delegate void TotalMethod(int type);//第一步delegate 方法签名 定义个方法的样子,如同接口    class Program    {        static void Main(string[] args)        {            //TotalMethod tm =new TotalMethod(Method1);//或者   非常建议    直接 +=或者=            TotalMethod tm = Method1 ;                        tm += Method2;                        tm += Method3;            tm(2);//一次性执行3个方法 tm.Invoke(3);//或者使用Invoke方法             Console.ReadLine();        }        static void Method1(int t) {            Console.WriteLine("Method1:"+t*10+"\t");        }        static void Method2(int t)        {            Console.WriteLine("Method2:" + t * 100 + "\t");        }        static void Method3(int t)        {            Console.WriteLine("Method3:" + t * 1000 + "\t");        }    }}

 效果:

 

 示例2:委托类型的数组。把委托当做参数,这个技巧一定要掌握,可以写出很精彩的代码,很像Javascript传方法。方法的Lambda表达式写法初次见面

/* *2015年1月3日23:12:13 aaronyang *网址:www.ayjs.net       www.8mi.me */using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace demo0103{    delegate void TotalMethod(ref int type);//第一步delegate 方法签名 定义个方法的样子,如同接口    ///     /// 处理TotalMethod方法,将转换后的数字,按照count数进行一定同样的数字相乘    /// 我没有定义一个和此委托方法签名一致的方法,使用的是Lambda表达式定义一个方法    ///     ///     ///     /// 
delegate int ProcessTotalMethod(TotalMethod total,int count); class Program { static void Main(string[] args) { //TotalMethod tm =new TotalMethod(Method1);//或者 非常建议 直接 +=或者= //TotalMethod tm = Method1 ; // tm += Method2; // tm += Method3; //tm(2);//一次性执行3个方法 //tm.Invoke(3);//或者使用Invoke方法 TotalMethod[] tms = { Method1, Method2, Method3 }; //委托数组 int initTypeNum=2; ProcessTotalMethod ptm = (x,y) => { x(ref initTypeNum);//将init按照10,100,1000倍相乘,并返回 Console.WriteLine("乘以倍数后的数字:" + initTypeNum ); //接下来连续乘以y个 initTypeNum for (int i = 0; i < y; i++) { initTypeNum *= initTypeNum; } return initTypeNum; }; Console.WriteLine("终于连续2次相乘后的数字:" + ptm(tms[0], 2)); Console.ReadLine(); } static void Method1(ref int t) { t = t * 10; Console.WriteLine("Method1:"+t+"\t"); } static void Method2(ref int t) { t = t * 100; Console.WriteLine("Method2:" + t + "\t"); } static void Method3(ref int t) { t = t * 1000; Console.WriteLine("Method3:" + t + "\t"); } }}

效果:

 

 1.2  框架自带好的常用的 Action<T1,[T2]...[T8]>和Func<T1,T2..[T8]>     可查看我写的Func教程:

        Action 是个 void的委托,其中T1,T2..T8都是方法的参数,而Func是个,最后一个泛型参数是返回值,前面是方法的参数,例如Func<int,string,double> 那么最后一个double就是返回值类型,前面是方法签名的参数,等同于定义了

        delegate double Method1(int,string);

        关于Func可以写出很多很精彩的代码,真的很期待大家的发挥。

 

 1.3  多播委托

 如1.1示例1讲解的就是一个多播委托的简单的例子。

 aaronyang的认识: 一个委托绑定了多个方法,然后执行委托,如果委托定义的方法签名是void,则依次执行,如果报错,迭代就停止。如果委托定义的方法签名有返回值,例如像int,string等类型,就只会看到最后一个结果。委托可以使用+=增加方法调用,使用

  -=删除方法调用。

接下来,演示个Delegate类的GetInvocationList()方法返回一个Delegate数组

 

1.4 匿名方法其实在1.3我们已经见过了,直接 (方法参数)=>{ 方法体}   来简易的 定义一个方法类型。如果只有一个方法参数,括号可以去掉,例如 x=>{方法体}

      也可以稍微烦一点的写法, 增加一个delegate关键字,例如  Func<string,string> a=delegate(string s){ return s} 也等同于  Func<string,string> a = s=>{return s} 也等同于   Func<string,string> a = s =>"修饰后:"+s;

 

1.5 闭包:Lambda表达式可以访问Lambda表达式外的变量;可能问题:假如多线程环境,修改了lambdawai的变量值,会使结果可能不正确了。

int lambdawai = 5;            Func
f = x => x+lambdawai; Console.WriteLine(lambdawai); // 输出 5; Console.WriteLine(f(3)); // 输出 8;

 

*1.6  C# 5.0很大的改变,foreach语句的闭包    参考文章:

个人小试:Win8.1 没发现。。问题

案例:下面代码输出什么,C#4.0 输出5,5,5,5,5   C#5.0输出1,2,3,4,5

 

int[] data = new int[] { 1, 2, 3, 4, 5 };            List
> actions = new List
>(); foreach (int x in data) { actions.Add(() => x); } foreach (var foo in actions) { Console.WriteLine(foo()); }

 

C# 4.0 foreach执行原理:的确输出5个5

int[] data = new int[] { 1, 2, 3, 4, 5 };            List
> actions = new List
>(); IEnumerator e = data.GetEnumerator(); int x = 0; while (e.MoveNext()) { x = (int)e.Current; actions.Add(() => x); } foreach (var foo in actions) { Console.WriteLine(foo()); }

注意迭代变量x是在循环块外部被定义的。

这里涉及到一个很重要的概念,闭包,在Lambda表达式中,我们使用了外层的自由变量x,注意,在调用lambda表达式的时候,x会被求值,而这个定义在外部的x变量在循环终了等于5,这是为什么都是输出5的原因

 

C# 5.0 foreach执行原理:的确 1,2,3,4,5

int[] data = new int[] { 1, 2, 3, 4, 5 };            List
> actions = new List
>(); IEnumerator e = data.GetEnumerator(); while (e.MoveNext()) { int x = 0; x = (int)e.Current; actions.Add(() => x); } foreach (var foo in actions) { Console.WriteLine(foo()); }

这一次,我们将x定义到块的内部。因此每当循环执行一次,都会产生一个局部变量x,闭包就会对每一个迭代单独求值,所以输出就是我们期望的12345了

如果想要得到1,2,3,4,5,可以修改代码:

int[] data = new int[] { 1, 2, 3, 4, 5 };            List
> actions = new List
>(); foreach (int x in data) { int x1 = x; actions.Add(() => x1); } foreach (var foo in actions) { Console.WriteLine(foo()); }

 

 

1.7 事件-特殊的委托,例如winform的button的Click事件

     自定义事件,泛型事件的调用,事件侦听器,弱性事件,泛型弱性事件,Expression的用法,内容很多,将在下一章单独讲吧。

 

留个问题:单个委托绑定2次相同的方法,执行该委托,方法会执行几次

        例如 A+=a;A+=a;A(); 

 

======安徽六安=========www.ayjs.net==========aaronyang========杨洋========www.8mi.me==========

 

转载地址:http://irjwl.baihongyu.com/

你可能感兴趣的文章
cms无法登陆
查看>>
JavaScript中事件处理
查看>>
VSTO 向office文档中插入内容
查看>>
【百度地图API】关于如何进行城市切换的三种方式
查看>>
How to provide highlighting with Spring data elasticsearch
查看>>
MongoDB 游标
查看>>
即将搭载人工智能芯片的华为Mate10,究竟会为业界带来什么?
查看>>
Android实现登录小demo
查看>>
AgentWeb是基于Android WebView一个功能完善小型浏览器库
查看>>
开放数据中心联盟推8个云计算应用模型
查看>>
学习数据分析的“里程碑”是什么?
查看>>
数据科学与DevOps之间的差距还有救吗?
查看>>
信息化一周回顾:金融业大数据十大趋势
查看>>
Http、TCP/IP协议与Socket之间的区别
查看>>
文思海辉:智慧数据避免企业成为大数据时代落伍者
查看>>
迅雷发布“星域CDN” 做条颠覆市场的鲶鱼
查看>>
英国《数字经济法案》
查看>>
Asp.net与Flex交互测试记录
查看>>
运维前线:一线运维专家的运维方法、技巧与实践1.8 运维自动化依赖的团队模型...
查看>>
《树莓派渗透测试实战》——第1章 树莓派和Kali Linux基础知识
查看>>