zoukankan      html  css  js  c++  java
  • 各版本.NET委托的写法回顾

    http://www.csharpwin.com/csharpspace/7548r2766.shtml   在《关于最近面试的一点感想》一文中,Michael同学谈到他在面试时询问对方“delegate在.net framework1.1,2.0,3.5各可以怎么写”这个问题。于是乎,有朋友回复道“请问楼主,茴香豆的茴有几种写法”,“当代孔乙己”,独乐,众 乐。看了所有的评论,除了某些朋友认为“的确不该不知道这个问题”之外,似乎没有什么人在明确支持楼主。 不过我支持,为什么?因为我也提过出这样的问题:各版本.NET委托的写法有何不同? 这样,我们暂且不提应聘“高级开发人员”的人,在“自称熟悉各版本.NET框架”的前提下,是否应该知道这个答案。我们也暂且不提Michael同学提问的“目的”是什么。老赵就先单独针对这个问题进行解释,然后谈谈自己为什么会提出这个问题吧。 可能有一件事情需要说在前面,那就是:委托本身其实从来没有改变过,改变的一直都是委托的“写法”。因此更确切地说,改变的只是“编译器”。而本文所有内 容都用C#来实现,其实谈得也都是C#编译器本身——但是其实VB.NET也有变化埃再由于.NET版本和C#版本的关系也是非常密切的,因此全文就使 用.NET版本进行指代了。 .NET 1.x中委托的写法 委托,如果不追究细节,从表面上来看我们可以将其通俗地理解为一个安全的“函数指针”。当然,这个函数指针其实也是一个对象,有自己的成员,也会封装了被调用方的上下文等等。至于委托的定义和使用方式,则是这样的:
    1. public delegate int SomeDelegate(string arg1, bool arg2);
    2. public static int SomeMethod(string arg1, bool arg2) { return 0; }
    3. public class SomeClass
    4. {
    5.     public int SomeMethod(string a1, bool a2) { return 0; }
    6.     public event SomeDelegate SomeEvent;
    7. }
    8. static void Main(string[] args)
    9. {
    10.     SomeClass someClass = new SomeClass();
    11.     SomeDelegate someDelegate = new SomeDelegate(someClass.SomeMethod);
    12.     someClass.SomeEvent += new SomeDelegate(SomeMethod);
    13. }
    可见,在.NET 1.x中需要使用new DelegateType(...)的方式来创建一个委托对象。不过,作为委托对象内部的方法它既可以是实例方法,也可以是静态方法。此外,方法只需要匹配委托类型的签名和返回值即可,方法参数的名称不会成为约束。 嗯,就是这么简单。 .NET 2.0中委托的写法 .NET委托引入了范型,且写法略有简化:
    1. public delegate TResult MyFunc(T1 a1, T2 a2);
    2. public static int SomeMethod(string a1, bool a2) { return 0; }
    3. static void Main(string[] args)
    4. {
    5.     MyFunc<stringboolint> myFunc = SomeMethod;
    6. }
    在.NET 2.0中,new DelegateType已经可以省略,开发人员可以直接将方法赋值给一个委托对象的引用。当然,这个改进不值一提,.NET 2.0中委托写法的关键在于引入了“匿名方法”:
    1. public static void TestRequest(string url)
    2. {
    3.     WebRequest request = HttpWebRequest.Create(url);
    4.     request.BeginGetResponse(delegate(IAsyncResult ar)
    5.     {
    6.         using (WebResponse response = request.EndGetResponse(ar))
    7.         {
    8.             Console.WriteLine("{0}: {1}", url, response.ContentLength);
    9.         }
    10.     },
    11.     null);
    12. }
    匿名方法,简单地说就是内联在方法内部的委托对象,它的关键便在于形成了一个闭包(委托执行时所需的上下文)。如上面的代码 中,BeginGetResponse的第一个参数(委托)可以直接使用TestRequest方法的参数url,以及方法内的“局部”变量 request。如果没有匿名函数这个特性的话,代码写起来就麻烦了,例如在.NET 1.x中您可能就必须这么写:
    1. public static void TestRequest(string url)
    2. {
    3.     WebRequest request = HttpWebRequest.Create(url);
    4.     object[] context = new object[] { url, request };
    5.     request.BeginGetResponse(TestAsyncCallback, context);
    6. }
    7. public static void TestAsyncCallback(IAsyncResult ar)
    8. {
    9.     object[] context = (object[])ar.AsyncState;
    10.     string url = (string)context[0];
    11.     WebRequest request = (WebRequest)context[1];
    12.     using (WebResponse response = request.EndGetResponse(ar))
    13.     {
    14.         Console.WriteLine("{0}: {1}", url, response.ContentLength);
    15.     }
    16. }
    此时,我们往往会发现,开发人员需要花费大量的精力,为一小部分代码维护一大段上下文。例如在这段代码中,我们会将url和request对象塞入一个 object数组中,在回调函数中再通过危险的Cast操作恢复数据。如果您希望“强类型”,那么只能为每个回调创建一个新的上下文对象,维护起来可能更 加麻烦——要知道,在并行编程,异步调用越来越重要的今天,如果没有匿名方法自动保留上下文的特性,开发人员会为这些“额外工作”疲于奔命的。 可能您会说,匿名方法的可读性不佳,因为需要“内联”。一个方法中内联太多,维护成本就上去了,所以匿名方法并不推荐使用。我想说的是,您错了。如果为了可维护性,要将方法独立拆开,也可以利用匿名方法的优势:
    1. public static void TestRequest(string url)
    2. {
    3.     WebRequest request = HttpWebRequest.Create(url);
    4.     request.BeginGetResponse(delegate(IAsyncResult ar)
    5.     {
    6.         TestAsyncCallback(ar, request, url);
    7.     }, null);
    8. }
    9. public static void TestAsyncCallback(IAsyncResult ar, WebRequest request, string url)
    10. {
    11.     using (WebResponse response = request.EndGetResponse(ar))
    12.     {
    13.         Console.WriteLine("{0}: {1}", url, response.ContentLength);
    14.     }
    15. }
    如果借助.NET 3.5中的Lambda表达式,代码可以写的更简单易读:
    1. public static void TestRequest(string url)
    2. {
    3.     WebRequest request = HttpWebRequest.Create(url);
    4.     request.BeginGetResponse(ar => TestAsyncCallback(ar, request, url), null);
    5. }
    以上就总结了各版本.NET委托的写法。
  • 相关阅读:
    第二章 图像的显示
    c++ 使用PI
    c++函数写的都对,还是说incompatible或者not found的解决办法
    我理解的直方图均衡化
    解决360WiFi有时候手机连接不上
    c# 16进制byte转成int
    VS2010 代码突然改变字体 解决办法
    荣耀手机恢复那些“不再提示”的设置
    mfc视类中错误:IntelliSense: declaration is incompatible with。。。解决方案
    [原] Android 自定义View步骤
  • 原文地址:https://www.cnblogs.com/adodo1/p/4327350.html
Copyright © 2011-2022 走看看