美文网首页
C# 委托 02

C# 委托 02

作者: JeetChan | 来源:发表于2019-08-22 11:24 被阅读0次

声明

本文内容来自微软 MVP solenovex 的视频教程——真会C#? - 第4章 委托、事件、Lambda表达式(完结),大致和第 2 课—— 4.1 委托(下) 对应。可在 GitHub 中查看 C# 视频教程的配套PPT

本文主要包括以下内容:

  1. 实例方法目标和静态方法目标
  2. 泛型委托类型
  3. Func 和 Action 委托
  4. 委托 vs 接口
  5. 委托的兼容性

实例方法目标和静态方法目标

当一个实例方法被赋值给委托对象的时候,这个委托对象不仅要保留着对方法的引用,还要保留着方法所属实例的引用。System.DelegateTarget属性就代表着这个实例。如果引用的是静态方法,那么Target属性的值就是null

public delegate void ProgressReporter (int percentComplete);

class Test
{
    static void Main()
    {
        X x = new X();
        ProgressReporter p = x.InstanceProgress;
        p(99); // 99
        Console.WriteLine (p.Target == x); // True
        Console.WriteLine (p.Method); // Void InstanceProgress(Int32)
    }
}

class X
{
    public void InstanceProgress (int percentComplete)
    => Console.WriteLine (percentComplete);
}

泛型委托类型

委托类型可以包含泛型类型参数。public delegate T Transformer<T> (T arg);

public class Util
{
    public static void Transform<T> (T[] values, Transformer<T> t)
    {
        for (int i = 0; i < values.Length; i++)
            values[i] = t (values[i]);
    }
}

class Test
{
    static void Main()
    {
        int[] values = { 1, 2, 3 };
        Util.Transform (values, Square); // Hook in Square
        foreach (int i in values)
            Console.Write (i + " "); // 1 4 9
    }
    
static int Square (int x) => x * x;
}

Func 和 Action 委托

使用泛型委托,就可以写出这样一组委托类型,它们可调用的方法可以拥有任意的返回类型和任意(合理)数量的参数。

delegate TResult Func <out TResult> ();
delegate TResult Func <in T, out TResult> (T arg);
delegate TResult Func <in T1, in T2, out TResult> (T1 arg1, T2 arg2);
//... and so on, up to T16

delegate void Action ();
delegate void Action <in T> (T arg);
delegate void Action <in T1, in T2> (T1 arg1, T2 arg2);
// ... and so on, up to T16

public static void Transform<T> (T[] values, Func<T,T> transformer)
{
    for (int i = 0; i < values.Length; i++)
        values[i] = transformer (values[i]);
}

委托 vs 接口

委托可以解决的问题,接口都可以解决。

什么情况下更适合使用委托而不是接口呢?当下列条件之一满足时:

  • 接口只能定义一个方法
  • 需要多播能力
  • 订阅者需要多次实现接口
class Squarer : ITransformer
{
    public int Transform (int x) => x * x;
}

class Cuber : ITransformer
{
    public int Transform (int x) => x * x * x;
}

// ...

static void Main()
{
    int[] values = { 1, 2, 3 };
    Util.TransformAll (values, new Cuber());
    foreach (int i in values)
        Console.WriteLine (i);
}

委托的兼容性

委托类型

委托类型之间互不相容,即使方法签名一样:

delegate void D1();
delegate void D2();
// ...

D1 d1 = Method1;
D2 d2 = d1; // Compile-time error

委托实例

如果委托实例拥有相同的方法目标,那么委托实例就认为是相等的。

delegate void D();
// ...

D d1 = Method1;
D d2 = Method1;
Console.WriteLine (d1 == d2); // True

参数

当你调用一个方法时,你提供的参数(argument)可以比方法的参数(parameter)定义更具体。委托可以接受比它的方法目标更具体的参数类型,这个叫ContraVariance。和泛型类型参数一样,委托的variance仅支持引用转换。

delegate void StringAction (string s);

class Test
{
    static void Main()
    {
        StringAction sa = new StringAction (ActOnObject);
        sa ("hello");
    }
    static void ActOnObject (object o) => Console.WriteLine (o); // hello
}

返回类型

调用方法时,你可以得到一个比请求的类型更具体的类型的返回结果。委托的目标方法可以返回比委托描述里更具体的类型的返回结果,Covariance

delegate object ObjectRetriever();

class Test
{
    static void Main()
    {
        ObjectRetriever o = new ObjectRetriever (RetrieveString);
        object result = o();
        Console.WriteLine (result); // hello
    }
    
static string RetrieveString() => "hello";
}

泛型委托类型参数的variance

  • Covariance,out
  • ContraVariance,in
C# 委托

参考

Delegates (C# Programming Guide)
Delegate Class
MulticastDelegate Class

相关文章

  • 目录 - C#

    总目录 C# 第01局:泛型 C# 第02局:反射 C# 第03局:特性 C# 第04局:委托 C# 第05局:事...

  • C# 委托 02

    声明 本文内容来自微软 MVP solenovex 的视频教程——真会C#? - 第4章 委托、事件、Lambda...

  • C# 委托

    C#委托 C#中的委托(Delegate)类似于C或C++中函数的指针。委托(Delegate)是存有对某个方法的...

  • 教小明学一点点编程—C#篇(0)

    像小明这样使用C#的新同学,一定都会被C#的复杂的委托事件机制所困惑,那么我们不如解释一下什么是C#中委托。 委托...

  • C#委托 匿名函数 Lambda

    C# 中委托的发展#在 C# 1.0 中,通过使用在代码中其他位置定义的方法显式初始化委托来创建委托的实例。 C#...

  • 2020-02-19

    C# 委托 (一)—— 委托、 泛型委托与Lambda表达式 原创wnvalentin 最后发布于2018-08-...

  • (转).NET面试题系列[7] - 委托与事件

    委托和事件 委托在C#中具有无比重要的地位。 C#中的委托可以说俯拾即是,从LINQ中的lambda表达式到(包括...

  • 委托及其用法

    C#委托使用详解(Delegates) 1. 委托是什么? 其实,我一直思考如何讲解委托,才能把委托说得更透彻。说...

  • C# 高级语言总结

    后续 1 C# 委托 委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 ...

  • C#匿名方法、Lambda表达式和各种泛型委托

    Linq查询与高级C#编程机器理论研究基础 C#委托解决的是对象之间的逆向传递问题,其次,委托还有其他的用途(匿名...

网友评论

      本文标题:C# 委托 02

      本文链接:https://www.haomeiwen.com/subject/udxnsctx.html