有关委托的进化

.NET 1.x中的委托

public delegate int SomeDelegate(string arg1, bool arg2);
public static int SomeMethod(string arg1, bool arg2) {
    return 0;
}
public class SomeClass {
    public int SomeMethod(string a1, bool a2) {
        retrun 0;
    }
    public event SomeDelegate SomeEvent;
}

static void Main(string[] args) {
    SomeClass someClass = new SomeClass();
    SomeDelegate someDelegate = new SomeDelegate(someClass.SomeMethod);
    someDelegate.SomeEvent += new SomeDelegate(SomeMethod);
}

.NET 1x中需要使用new DelegateType(…)的方式来创建一个委托对象。作为委托对象内部的方法既可以是成员方法也可以是静态方法。

.NET 2.0中委托

public delegate TResult MyFunc<T1, T2, TResult>(T1 a1, T2 a2);
public static int SomeMethod(string a1, bool a2) {
    return 0;
}
static void Main(string[] args) {
    MyFunc<string, bool, int> myFunc = SomeMethod;
}

在2.0中,new DelegateType可以省略,开发人员可以直接将方法赋值给一个委托对象的引用。下面看看新引入的“匿名方法”:

public static void TestRequest(string url) {
    WebRequest request = HttpWebRequest.Create(url);
    request.BeginGetResponse(delegate(IAsyncResult ar) {
        using (WebResponse response = request.EndGetResponse(ar)) {
            Console.WriteLine("{0}: {1}", url, response.ContentLength);
        }
    },
    null);
}

匿名方法,简单地说就是内联在方法内部的委托对象,它的关键便在于形成了一个闭包(委托执行时所需的上下文)。如上面的代码中,BeginGetResponse的第一个参数(委托)可以直接使用TestRequest方法的参数url,以及方法内的“局部”变量request。如果没有匿名函数这个特性的话,代码写起来就麻烦了,例如在.NET 1.x中您可能就必须这么写:

public static void TestRequest(string url)
{
    WebRequest request = HttpWebRequest.Create(url);
    object[] context = new object[] { url, request };
    request.BeginGetResponse(TestAsyncCallback, context);
}

public static void TestAsyncCallback(IAsyncResult ar)
{ 
    object[] context = (object[])ar.AsyncState;
    string url = (string)context[0];
    WebRequest request = (WebRequest)context[1];

    using (WebResponse response = request.EndGetResponse(ar))
    {
        Console.WriteLine("{0}: {1}", url, response.ContentLength);
    }
}

可读性增强的匿名写法如下:

public static void TestRequest(string url)
{
    WebRequest request = HttpWebRequest.Create(url);
    request.BeginGetResponse(delegate(IAsyncResult ar)
    {
        TestAsyncCallback(ar, request, url);
    }, null);
}

public static void TestAsyncCallback(IAsyncResult ar, WebRequest request, string url)
{
    using (WebResponse response = request.EndGetResponse(ar))
    {
        Console.WriteLine("{0}: {1}", url, response.ContentLength);
    }
}

.NET 3.5中可以使用Lambda表达式

public static void TestRequest(string url)
{
    WebRequest request = HttpWebRequest.Create(url);
    request.BeginGetResponse(ar => TestAsyncCallback(ar, request, url), null);
}

欢迎留言

avatar
  Subscribe  
Notify of