|
| |
名片设计 CorelDRAW Illustrator AuotoCAD Painter 其他软件 Photoshop Fireworks Flash |
|
一、 简介 所有的方式都使用一个来自于一样集合的元素的子集。在C# 2.0中,可选元素集将会继承增长。从历史上看-除了C++内联方式之外-方式都要求有一个名字、一个返回类型和一个方式体。而且可选择地,方式可以使用存取修饰符和一个参数列表。在C# 2.0中,方式名已经从必需的变成了可选的。 C# 2.0(一般就代表.NET)引入了匿名方式。一个匿名方式可以被用在任何使用代理且该代理被定义为内联的情况下,它不需要方式名,而具有可选的参数和一个方式体。 为了使用匿名方式,你需要了解什么是代理。因此,在我们具体讨论何时使用匿名方式以及匿名方式的局限性之前,先让我们简要地回顾一下代理。 二、 代理回顾 匿名方式对于声明和使用代理来说是一种压缩方法(假如你对什么是代理还有疑问,请继承阅读;否则,可以跳过下面的这一部分)。代理,作为一种指向函数签名的指针,在.NET语言之前的语言中就已存在。切记,在计算机中一切其实都是位和字节。通过引入函数指针技术,有可能动态地把一些未来的目前尚未知的函数赋给指针,并由此诞生了事件。 函数指针的基本使用方式是,可以把一个函数的地址赋给一个单一的指针。为了通过一个指针来调用该函数,程序员要对之进行检查以决定是否这个指针为null,然后间接地通过这个指针调用这个函数。总之,要使用指针,必须进行null检查,而现在\"一个指针对应一个函数\"作为一种限制也该到结束的时候了。 回顾一下来分析,代理会成为原始函数指针的下一个进化替代者。一个代理即是一个类,它对该指针进行了封装;隐含地,.NET中的代理是multicast代理。作为一个multicast代理仅仅意味着不再存在\"一个函数对应一个指针\"的限制,因为multicast代理类包含一个指针列表。包含一个内部列表意味着多于一个函数的地址可以被赋值给一个单一的代理。当该代理-你可以认为是\"事件\"-被激发或调用时,所有的内部列表函数被调用。 注重 在C#中,我们调用代理的方法就象从前我们调用方式以及调用所有的赋值函数相同;但是我们仍旧能够进行null检查。在Visual Basic.NET中,null检查隐含在激活事件行为中。 在C#中,函数地址通过使用一个重载的+=操作符插入到一个列表中并且经由一个重载的-=操作符而被删除。C#还支持手工地定义添加和删除块;添加和删除对于代理恰似get和set对于属性。 在C# 1.0和C# 1.1中,典型情况下,我们把代理实例赋给事件属性。例如,在WinForms中,一个Button控件暴露一个Click事件。Click的代理类型是EventHandler。EventHandler是一个以对象和EventArgs为参数的方式。因此,我们可以用匹配代理EventHandler的签名的任何方式来初始化一个EventHandler对象并且把代理赋给Click。下面是该代码看上去的样子: private void Form1_Load(object sender, EventArgs e) { button1.Click += new EventHandler(OnClick);} private void OnClick(object sender, EventArgs e) { Debug.WriteLine(\"button1 clicked\");} 因为WinForms的表单设计器和WebForms的页面设计器自动地添加代理绑定;所以,我们有可能不需要手工式地绑定代理而建立大量的代码。 三、 匿名方式是内联代理 通常,当我们使用代理时,我们总是有一个方式。该方式的签名匹配代理的签名规定并且能被用来初始化一个代理实例。匿名方式用于把方式和代理的初始化压缩到一个单一的位置。 通过使用前一节的例子,我们已看到代理new EventHandler的实例化是怎样区别于用来初始化该代理的方式OnClick的。这部分代码能被压缩成一个匿名方式: private void Form1_Load(object sender, EventArgs e){ button1.Click += delegate { Debug.WriteLine(\"button1 clicked\"); }; } 为了创建该匿名方式,请注重我们删除了OnClick的方式头并且用OnClick的方式体的单词delegate代替了EventHandler代理的构造器。其所导致的结果行为是一样的。假如我们想使用事件参数,我们通常与代理相关联,我们可以在单词delegate之后添加一可选的参数列表: private void Form1_Load(object sender, EventArgs e){ button1.Click += delegate(object s, EventArgs ev) { Debug.WriteLine(\"object is \" + s.ToString()); }; } 假如你定义代理参数,它们必须匹配代理类型所定义的参数。例如,Click的类型是EventHandler,因此假如参数存在,它们必须匹配EventHandler的参数对象和EventArgs。 匿名方式可以被使用在任何需要使用代理的地方。匿名方式可以使用ref和out参数,但是不能使用全局范围的reference ref或out参数。匿名方式不能使用unsafe编码,并且匿名方式不能以使得分支行为跳出匿名方式的代码块的方法来使用goto,break或continue等语句。 四、 市场调查结果 匿名方式是好东西吗?市场调查证实匿名方式确实不错,因为它们能够减少由于实例化代理和减少分离方式所导致的代码开销。而且市场调查还证实匿名方式增强了可用性和可维护性。我认为良好命名的方式也可以实现这一点。请看下面的代码轻易维护吗? private void Form1_Load(object sender, EventArgs e) { BindClick(delegate { Debug.WriteLine(\"button1 click\"); }); } private void BindClick(EventHandler handler) { button1.Click += handler; } 在这个例子中,我们把一个代理传递给一个方式-通过把该代理作为一个匿名方式传递。仅是保持圆括号、分号和方括号的顺序和个数就已令人十分头疼。 假如引用经典示例来说明,那就是匿名方式仅仅是因剔除了线程(它们使用代理)而减少了相应的创建代理和方式的开销。这倒是真的,但是线程并不常常使用并且想准确使用也异常困难。我在想,要想使代码更为秘密些而不是更为公开些该是多么谨慎的一件事情。 就语言方面来讲,我喜欢方式;但是作为一个实际开发中的事物,匿名方式也许仅是微软的某个发明者有点太智慧的一种证实。 五、 总结 匿名方式是可以存在没著名字的方式的证实-它们可以被定义并使用在任何能够使用代理的地方。代理是事件处理器的包装器。匿名方式到底有多大的实用性和普遍使用价值还有待于进一步的实践证实。我怀疑,匿名方式将不会比运算符重载有更大的用途,并且其使用也会少之又少;但是匿名方式现在已是.NET的一部分,所以在阅读代码时能够识别出它们来还是很有必要的。 返回类别: 教程 上一教程: .NET 框架类库(上) 下一教程: .Net开放源码工程之二---正则表达式函数库 您可以阅读与"对C# 2.0中匿名方式的怀疑分析"相关的教程: · 治理三元式的新思路,涉及到查询时好像可以借用Social Network的思想 · .net缓存应用与分析 · ASP.NET下MVC设计模式的实现 · MS.Net CLR 扩展PE结构分析2 · 深入理解.NET 的JIT编译方法 |
| 快精灵印艺坊 版权所有 |
首页 |
||