委托是函数指针的升级版
一切皆地址
直接调用与间接调用,CPU执行的指令是的
1.actio委托,只能指向没有返回类型的函数。func委托,指向有返回类型的函数。
class Calculator
{
public void Report()
{
Console.WriteLine("I have 3 methods ");
}
public int Add(int a ,int b)
{
int result = a + b;
return result;
}
public int Sub(int a ,int b)
{
int result = a * b;
return result;
}
}
//main函数中
Calculator calculator = new Calculator();
Action action = new Action(calculator.Report);//只能指向void方法
calculator.Report();//直接调用
action.Invoke();//间接调用
action();
//前两个为函数的参数类型,目标函数返回的类型
Func<int, int, int> func1 = new Func<int, int, int>(calculator.Add);
Func<int, int, int> func2 = new Func<int, int, int>(calculator.Sub);
int x = 100;
int y = 200;
int z = 0;
z = func1(x, y);
Console.WriteLine(z);
z = func2(x, y);
Console.WriteLine(z);
2.自定义委托:返回值得数据类型一直,参数列表在个数和数据类型上一致。
Calc calc1 = new Calc(calculator.Add);
Calc calc2 = new Calc(calculator.Sub);
Calc calc3 = new Calc(calculator.Mul);
Calc calc4 = new Calc(calculator.Div);
double a = 100;
double b = 200;
double c = 0;
c = calc1.Invoke(a,b);
Console.WriteLine(c);
c=calc2(a,b);
3.模板方法和回调方法:
using System;
namespace CDelegate
{
class Program
{
public delegate double Calc(double x, double y);
static void Main(string[] args)
{
ProductFactory productFactory = new ProductFactory();
WrapFactory wrapFactory = new WrapFactory();
Func<Product> func1 = new Func<Product>(productFactory.MakePuzza);
Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);
Logger logger = new Logger();
Action<Product> log = new Action<Product>(logger.Log);
Box bos1 = wrapFactory.WrapProduct(func1,log);
Box bos2 = wrapFactory.WrapProduct(func2,log);
Console.WriteLine(bos1.Product.Name);
Console.WriteLine(bos2.Product.Name);
}
}
class Logger
//记录程序运行状态,回调方法
{
public void Log(Product product)
{
Console.WriteLine("Product '{0}' create at {1}. Price is {2}", product.Name, DateTime.UtcNow, product.Price);
}
}
class Product
{
public string Name { get; set; }
public double Price { get; set; }
}
class Box
{
public Product Product { get; set; }
}
class WrapFactory
{
public Box WrapProduct(Func<Product> getProduct,Action<Product> logCallback)
{
Box box = new Box();
Product product=getProduct.Invoke();
box.Product = product;
if(product.Price >= 50)
{
logCallback(product);
}
return box;
}
}
class ProductFactory
{
public Product MakePuzza()
{
Product product = new Product();
product.Name = "Pizza";
product.Price = 12;
return product;
}
public Product MakeToyCar()
{
Product product = new Product();
product.Name = "ToyCar";
product.Price = 100;
return product;
}
}
}
注意:
1.这是一种方法级别的紧耦合,要慎重
2.使可读性下降,debug难度增加
3.把委托回调,异步调用和多线程纠缠在一起,会让代码变得难以阅读和维护
4.委托使用不当有可能造成内存泄漏和程序性能下降。
4.委托的高级用法
多播委托:用一个委托封装多个委托
action1 += action2;
action2 +=action3;
action1.invoke();
隐式异步调用:BeginInvoke()自动生成一个分支线程,分支线程中调用封装的方法,会隐式异步调用
显示异步调用:
最后,由于委托容易出问题,尽量用接口代替委托