·天新网首页·加入收藏·设为首页·网站导航
数码笔记本手机摄像机相机MP3MP4GPS
硬件台式机网络服务器主板CPU硬盘显卡
办公投影打印传真
家电电视影院空调
游戏网游单机动漫
汽车新车购车试驾
下载驱动源码
学院开发设计
考试公务员高考考研
业界互联网通信探索
您现在的位置:天新网 > 软件开发 > .Net开发 > C#
[C# 基础知识系列]专题十:匿名方法解析
http://www.21tx.com 2012年12月04日

1 2 下一页

引言:

  感觉好久没有更新博客了的,真是对不住大家了。在这个专题中将介绍匿名方法,匿名方法看名字也能明白,当然就是没有名字的方法了(现实生活中也有很多这样的匿名过程,如匿名投票,匿名举报等等,相信微软在命名方面肯定是根据了生活中例子的),然而匿名方法的理解却不是仅仅是这一句话(这句话指的是没有名字的方法),它还有很多内容,下面就具体介绍下匿名方法有哪些内容

一、匿名方法

  之前一直认为匿名方法是在C# 3.0中提出的,之前之所以这么认为主要是因为知道C# 3.0中提出了匿名类型,所以看到匿名方法就很理所当然的认为也是在C# 3.0中提出来,然而经过系统的学习C#特性后才发现匿名方法在C# 2.0 的时候就已经提出来了,从特性的提出发展中可以看出,微软的团队是非常有计划的,后面的特性其实在之前特性的提出就已经计划好,并且后面的特性都是之前特性演变而来,之所以有新特性的提出,主要是为了方便大家编写程序,减轻程序员的工作,让编译器去执行更加复杂的操作,使程序员可以把精力放在实现自己系统的业务逻辑方法(这也是微软的主要思想,也是大部分软件所强调的良好的用户体验),然而匿名方法也正是建立在C#1.0中委托的基础上的(同时C# 2.0中对委托有所增强,提出了泛型委托,以及委托参数的协变和逆变,具体的可以参考本系列的前面专题),下面就具体介绍下为什么说匿名方法是如何建立在委托基础之上的(委托是方法的包装,匿名方法也是方法,只是匿名方法是没有名字的方法而已,所以委托也可以包装匿名方法)。

  首先,先介绍下匿名方法的概念,匿名方法——没有名字的方法(方法也就是数学中的函数的概念),匿名方法只是在我们编写的源代码中没有指定名字而已,其实编译器会帮匿名方法生成一个名字,然而就是因为在源代码中没有名字,所以匿名方法只能在定义的时候才能调用,在其他地方不能被调用(匿名方法把方法的定义和方法的实现内嵌在一起),下面通过一个例子来看看匿名方法的使用和如何与委托关联起来的:

namespace 匿名方法Demo   
{   
    class Program   
    {   
        // 定义投票委托   
        delegate void VoteDelegate(string name);   
       
        static void Main(string[] args)   
        {   
            // 实例化委托对象   
            VoteDelegate votedelegate = new VoteDelegate(new Friend().Vote);   
       
            // 使用匿名方法的代码   
            // 匿名方法内联了一个委托实例(可以对照上面的委托实例化的代码来理解)   
            // 使用匿名方法后,我们就不需要定义一个Friend类以及单独定义一个投票方法   
            // 这样就可以减少代码量,代码少了,阅读起来就容易多了,以至于不会让过多的回调方法的定义而弄糊涂了   
            //VoteDelegate votedelegate = delegate(string nickname)   
            //{   
            //    Console.WriteLine("昵称为:{0} 来帮Learning Hard投票了", nickname);   
            //};   
       
            // 通过调用托来回调Vote()方法   
            votedelegate("SomeBody");   
            Console.Read();   
        }   
    }   
       
    public class Friend   
    {   
        // 朋友的投票方法   
        public void Vote(string nickname)   
        {   
            Console.WriteLine("昵称为:{0} 来帮Learning Hard投票了", nickname);   
        }   
    }   
}

因为前段时间参加了51博客大赛,在投票阶段也拉了好多朋友来帮忙投票的,所以为了感谢他们,所以上面就以投票作为例子来引出匿名方法,注释的部分中已经解释了匿名方法的好处的,可以帮助我们减少书写代码量,便于阅读,然而上面地方可以使用匿名方法来代替委托呢?是不是所有使用委托的地方我们都需要用匿名方法去代替的呢?事实不是这样的,因为匿名方法是没有名字的方法,所以在其他地方就不能被调用,所以不具有复用作用,并且匿名方法自动形成"闭包"(如果对于闭包不理解的朋友可以参考这两个链接:http://baike.baidu.com/view/648413.htm 和http://zh.wikipedia.org/wiki/闭包_(计算机科学) ,我理解的闭包大概是当一个函数中(外部函数)调用了另个一个函数(称内部函数)时,当内部函数使用了外部函数中的变量时,这样就可能会形成闭包。具体的概念可以参考上面的两个链接,关于闭包在后面部分也会给出相关的例子来帮助大家理解,由于匿名函数会形成闭包,这就会延长变量的生命周期)。所以如果委托包装的方法相对简单(就像上面代码中只是单独一行输出语句),并且这个方法在其他地方使用的频率很低时,这时候就可以考虑用匿名方法来代替委托。

二、使用匿名方法来忽略委托参数

  第一部分主要介绍了匿名方法的概念,使用以及介绍了我所理解的为什么会有匿名方法的提出(为了方便我们实例化委托实例,通过匿名方法可以内联委托实例,这样就避免额外定义一个实例方法,减少代码量,利于阅读),在这一部分中将介绍匿名方法的另外一个好处——忽略委托参数。下面通过一个示例代码来来帮助大家理解,代码中会有详细的注释,所以这里就不多说了,直接看代码了:

namespace 忽略委托参数Demo   
{   
    class Program   
    {   
        static void Main(string[] args)   
        {   
            // Timer类在应用程序中生成定期事件   
            System.Timers.Timer timer = new System.Timers.Timer();   
       
            // 该值指示是否引发Elapsed事件   
            timer.Enabled = true;   
       
            // 设置引发Elapsed事件的间隔   
            timer.Interval = 1000;   
       
            // Elapsed事件是达到间隔时发生,前面设置了时间间隔为1秒,   
            // 所以每一秒就会触发Elapsed事件,从而回调timer_Elapsed方法,输出当前的时间   
            // timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);   
       
            // 此时timer_Elapsed方法中的参数根本就不需要,所以我们可以使用匿名方法来省略委托参数   
            // 省略了参数后我们的代码就更加简洁了,看的多舒服啊   
            // 在开发WinForm程序中我们经常会用不到委托的参数,此时就可以使用匿名方法来省略参数   
            timer.Elapsed += delegate
            {   
                Console.WriteLine(DateTime.Now);   
            };   
       
            Console.Read();   
        }   
       
        public static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)   
        {   
            Console.WriteLine(DateTime.Now);   
        }   
    }   
}

运行结果为:

[C# 基础知识系列]专题十:匿名方法解析

  上面代码使用了匿名方法来省略委托参数,然而对于编译器而言,它还是会调用委托的构造函数来实例化委托,所以如果匿名方法能转换为多个委托类型时,此时如果省略了委托参数,编译器就不知道把匿名方法转化为哪个具体的委托类型,所以此时就会出现编译时错误,此时就必须人为的指定参数来告诉编译器如何实例化委托,下面就以创建线程为例子来帮助大家理解匿名方法省略委托参数所带来的问题(因为线程的创建涉及了两个委托类型: public delegate void ThreadStart() 和public delegaye void ParameterizedThreadStart(objec obj)):

class Program   
    {   
        static void Main(string[] args)   
        {   
            new Thread(delegate()   
                {   
                    Console.WriteLine("线程一");   
                });   
       
            new Thread(delegate(object o)   
            {   
                Console.WriteLine("线程二");   
            });   
       
            new Thread(delegate
            {   
                Console.WriteLine("线程三");   
            });   
            Console.Read();   
        }   
    }

此时第三个创建线程的代码会出现下面的编译错误:

上一篇: C#委托基础8——lambda表达式
下一篇: C#委托基础7——匿名方法

1 2 下一页

关于我们 | 联系我们 | 加入我们 | 广告服务 | 投诉意见 | 网站导航
Copyright © 2000-2011 21tx.com, All Rights Reserved.
晨新科技 版权所有 Created by TXSite.net