个人感觉和java的反射类相似

action委托

实例化该对象时,传入一个方法,后面就可以直接用action.Invoke()或者action()调用该方法

注意:这种委托只能获取无返回值的方法

Func委托

Func<原方法的参数列表类型….,返回值类型>
总之泛型列表的个数就是原方法参数列表的个数+1

自定义委托

public delegate 目标方法的返回值类型 委托名(目标方法的参数列表);

声明委托的位置尽量放在和其他类的同一层,如果不小心声明到其他类里面,则可以通过类.声明委托类来进行使用

委托的一般使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OrderTest
{
internal class Program
{
static void Main(string[] args) {
MyFactory myFactory = new MyFactory();
ProductFactory productFactory = new ProductFactory();
Func<Product> func1 = new Func<Product>(productFactory.Car);
Func<Product> func2 = new Func<Product>(productFactory.Dog);

Box box1 = myFactory.WrapProduct(func1);
Box box2 = myFactory.WrapProduct(func2);

}
}

class Product
{
public string Name { get; set; }
}

class Box
{
public Product Product { get; set; }
}

//包装工厂
class MyFactory
{
//将外部方法传入当前方法,通过外部方法的返回值做进一步操作
public Box WrapProduct(Func<Product> getProduct)
{
Box box = new Box();
//包装工厂获得生产工厂的产品之后进行包装
Product product = getProduct();
//将产品装入box
box.Product = product;
return box;
}
}
//生产工厂
class ProductFactory
{
public Product Car()
{
Product product = new Product();
product.Name = "Car";
return product;
}

public Product Dog()
{
Product product = new Product();
product.Name = "Dog";
return product;
}
}
}

给上述代码添加回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OrderTest
{
internal class Program
{
static void Main(string[] args) {
MyFactory myFactory = new MyFactory();
ProductFactory productFactory = new ProductFactory();
Action<Product> log = new Action<Product>(Logger.Log);

Func<Product> func1 = new Func<Product>(productFactory.Car);
Func<Product> func2 = new Func<Product>(productFactory.Dog);

Box box1 = myFactory.WrapProduct(func1,log);
Box box2 = myFactory.WrapProduct(func2, log);

}
}

class Product
{
public string Name { get; set; }
public int Price { get; set; }
}

class Box
{
public Product Product { get; set; }
}

//包装工厂
class MyFactory
{
public Box WrapProduct(Func<Product> getProduct,Action<Product> logProduct)
{
Box box = new Box();
//被动触发回调函数,根据price的价格来判断
Product product = getProduct();
if(product.Price >= 10)
{
logProduct(product);
}
box.Product = product;
return box;
}
}

class Logger
{
public static void Log(Product product)
{
Console.WriteLine("{0},{1},{2}", product.Name, DateTime.UtcNow, product.Price);
}
}
...
}

无论是模板方法还是回调方法,都是通过传入一个委托类型的参数,封装了一个外部的方法

委托的高级使用

多播委托

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HighOrder
{
internal class Program
{
static void Main(string[] args)
{
Student student1 = new Student() {Id = 2, penColor = ConsoleColor.Yellow};
Student student2 = new Student() { Id = 4, penColor = ConsoleColor.Blue };
Student student3 = new Student() { Id = 23, penColor = ConsoleColor.Green };


Action action1 = new Action(student1.printInformation);
Action action2 = new Action(student1.printInformation);
Action action3 = new Action(student1.printInformation);

//委托类型的也可以进行相加,相加的结果就是叠加方法
action1 += action2;
action1();
Console.ReadKey();
}
}
class Student
{
public int Id { get; set; }
public ConsoleColor penColor { get; set; }

public void printInformation()
{
Console.WriteLine(DateTime.UtcNow);
}
}
}

异步调用

隐式的异步调用

主线程

1
2
3
4
5
6
7
action1.BeginInvoke(null,null);
for (int i = 0; i < 10; i++)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("thread{0}", i);
Thread.Sleep(1000);
}

action1实现的程序

1
2
3
4
5
6
for (int i = 0; i < 2; i++)
{
Console.ForegroundColor = this.penColor;
Console.WriteLine(DateTime.UtcNow);
Thread.Sleep(1000);
}


委托变量使用BeginInvoke方法时,可以实现隐式的异步调用

显式的异步调用

  1. 创建多个线程去运行方法
  2. 使用Task运行方法