【C#】学习笔记(2)委托Delegate相关

泛型委托类型,同样是根据杨老师的视频来的。

直接上栗子🌰

  

 1 using System;
 2 
 3 namespace Demo
 4 {
 5     /// <summary>
 6     /// 泛型委托类型
 7     /// </summary>
 8     /// 
 9     public delegate T Transformer<T>(T arg); // 这里定义了一个返回类型为T 参数类型为T的泛型委托类型
10     public class Util
11     {
12         public static void Transform<T>(T[] values,Transformer<T> t)// 这里写了一个静态的泛型方法,包含了两个参数,第一个是泛型数组,第二个是泛型委托类型声明一个泛型委托变量
13         {
14             for (int i = 0; i < values.Length ; i++)
15             {
16                 values[i] = t(values[i]); // 遍历泛型数组的每一个值,并将遍历出的值通过t.Invoke()调用泛型委托,再将得到的值赋给当前位置的值。
17             }
18         }
19     }
20     public class Program
21     {
22         static int Square(int x) => x * x; 
23         public static void Main()
24         {
25             int[] values = { 1, 2, 3 };
26             Util.Transform(values, Square);
27             foreach (int i in values)
28             {
29                 Console.Write(i+" "); // 1 4 9
30             }
31         }
32     }
33 }

同样要注意的是泛型类型的委托同普通的委托一样,参数类型和返回类型必须要严格对应相等。

 

·Func和Action委托

Func是有返回类型的委托

1     delegate TResult Func<out TResult>();
2     delegate TResult Func<in T, out TResult>(T arg);
3     delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
4     // 输入最高可有有16个即in T1,in T2 ,...,in T16,但是out只有一个!嗯.对了也可以没有输入的.

Action是没有返回类型的委托

1     delegate void Action();
2     delegate void Action<in T>(T arg);
3     delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
4     //同样输入最高可到16个.

 

用Func委托对上面的栗子🌰进行改写。

Before:                        

    

After:

 

 

为什么可以用Func进行改写呢?

public delegate T Transformer<T>(T arg); 

 一个名叫Transformer的泛型委托,返回类型是泛型T,参数类型也是泛型T。

 

Func<T,T> t 

满足Func委托的要求。

 

·委托的应用场景

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

  • 接口只能定义一个方法
  • 需要多播能力
  • 订阅者需要多次实现接口

 栗子🌰

using System;

namespace Demo
{
    // 定义一个接口,有一个参数类型为int,返回类型也为int的函数
   public interface ITransformer
    {
        int Transform(int x);
    }
    // Square类实现ITransformer接口
    class Square : ITransformer
    {
        public int Transform(int x) => x * x;
    }
    // Cuber类实现ITransformer接口
    class Cuber : ITransformer
    {
        public int Transform(int x) => x * x * x;
    }
    // 定义一个工具类,里面有一个静态方法用于处理泛型委托类型相关的操作
    public class Util
    {
        public static void TransformAll<T>(T[] values,Func<T,T> t)
        {
            for (int i = 0; i < values.Length; i++)
            {
                values[i] = t(values[i]); 
            }
        }
    }
    public class Program
    {
        public static void Main()
        {
            int[] values1 = { 1, 2, 3 };
            Util.TransformAll(values1,new Square().Transform);// 因为不是静态方法所以只能用实例委托的方式
            foreach (int i in values1)
            {
                Console.Write(i+" "); // 1 4 9
            }

            Console.WriteLine();
            int[] values2 = { 1, 2, 3 };
            Util.TransformAll(values2, new Cuber().Transform);
            foreach (int i in values2)
            {
                Console.Write(i + " ");// 1 8 27
            }
        }
    }
}

即这种情况下(多次实现接口)适合委托。

委托类型之间互不相容。

编译不会通过。

委托可以接收比他的方法目标更具体的参数类型(ContraVariance),和泛型类型参数一样,委托的variance仅支持引用转换

 1 using System;
 2 
 3 namespace Demo
 4 {
 5     delegate void StringAction(string s);
 6     public class Program
 7     {
 8         static void ActOnObeject(object o) => Console.WriteLine(o);
 9         public static void Main()
10         {
11             StringAction sa = ActOnObeject;
12             sa("Hello");// Hello
13         }
14     }
15 }

 

  • int 到 long数值类转换非引用转换,所以不可以
  • int 到 object进行了装箱,所以也是不可以的

委托的返回类型也是可以具体化

 1 using System;
 2 
 3 namespace Demo
 4 {
 5     delegate object ObjectRetriever();
 6     public class Program
 7     {
 8         static string RetrieveString() => "Hello";
 9         public static void Main()
10         {
11             ObjectRetriever or = RetrieveString;
12             Console.WriteLine(or()); // Hello
13         }
14     }
15 }

委托类的类型就是委托实例的类型,即or()也是object类的。

自己理解画的图,如有错误欢迎指出。

 

posted @ 2019-07-25 22:48  BrainK_1400  阅读(409)  评论(2编辑  收藏  举报