函数指针
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace NamespaceEncasement
{
class Program
{
static void Main(string[] args)
{
Calculator c = new Calculator();
Action action = new Action(c.Report);//在这里Report后面没有(),说明这里是想用它的方法名,不是要调用这个方法。
//直接调用Report这个方法
c.Report();
//间接调用Report这个方法
action.Invoke();
//第三种方法
action();
Console.ReadKey();
}
}
class Calculator
{
public void Report()
{
Console.WriteLine("I have 3 methods");
}
}
}
上述代码可以直接打印
委托的简单使用里面有Action
委托和Func
委托
如果要调用Calculator
类的另外两个方法,用Func
委托
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace NamespaceEncasement
{
class Program
{
static void Main(string[] args)
{
Calculator c = new Calculator();
Action action = new Action(c.Report);//在这里Report后面没有(),说明这里是想用它的方法名,不是要调用这个方法。
//直接调用Report这个方法
c.Report();
//间接调用Report这个方法
action.Invoke();
//第三种方法
action();
Func<int, int, int> func1 = new Func<int, int, int>(c.Add);
Func<int, int, int> func2 = new Func<int, int, int>(c.Sub);
int x = 100;
int y = 200;
int z = 0;
z = func1.Invoke(x,y);
Console.WriteLine(z);
z = func2.Invoke(x,y);
Console.WriteLine(z);
Console.ReadKey();
}
}
class Calculator
{
public void Report()
{
Console.WriteLine("I have 3 methods");
}
public int Sub(int a, int b)
{
int result = a - b;
return result;
}
public int Add(int a, int b)
{
int result = a + b;
return result;
}
}
}
当然也可以直接调用
int x = 100;
int y = 200;
int z = 0;
z = func1(x,y);
Console.WriteLine(z);
z = func2(x,y);
Console.WriteLine(z);
委托的声明(自定义委托)
注意委托是一个类,所以理论上和Class Program
是平级的,应该写到Class Program
外面。另外注意,可以仿照指针的形式把类似c = calc1.Invoke(a, b);
语句中的Invoke
去掉。
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace NamespaceEncasement
{
public delegate double Calc(double x, double y);
class Program
{
static void Main(string[] args)
{
Calculator calculator = new Calculator();
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;
c = calc1.Invoke(a, b);
Console.WriteLine(c);
c = calc2.Invoke(a, b);
Console.WriteLine(c);
c = calc3.Invoke(a, b);
Console.WriteLine(c);
c = calc4.Invoke(a, b);
Console.WriteLine(c);
Console.ReadKey();
}
}
class Calculator
{
public double Sub(double a, double b)
{
double result = a - b;
return result;
}
public double Add(double a, double b)
{
double result = a + b;
return result;
}
public double Mul(double a, double b)
{
double result = a * b;
return result;
}
public double Div(double a, double b)
{
double result = a/b;
return result;
}
}
}
当然,C# 本身可以嵌套,也就说类里面还可以创建类,那么如果类里面创建了委托,使用该委托的时候,应该在委托前面加上类名.
模板方法
模板方法的好处是,只需要在一个类里面增加产品,其余的类都不用动,然后通过其中一个类来调用委托即可
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace NamespaceEncasement
{
class Program
{
static void Main(string[] args)
{
//实例一个产品工厂类
ProductFactory productFactory = new ProductFactory();
//实例一个包装工厂
WrapFactory wrapFactory = new WrapFactory();
//委托了一个做Pizza的方法
Func<Product> func1 = new Func<Product>(productFactory.MakePizza) ;
//委托了一个做Toycar的方法
Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);
Box box1 = wrapFactory.WrapProduct(func1);//调用委托
Box box2 = wrapFactory.WrapProduct(func2);
Console.WriteLine(box1.product.Name);
Console.WriteLine(box2.product.Name);
Console.ReadKey();
}
}
//声明一个产品类,只包含产品名属性
class Product
{
public string Name { get; set; }
//声明一个盒子类,包含产品属性
}
class Box
{
public Product product { get; set; }
}
/// <summary>
/// 模板方法
/// </summary>
//包装工厂类
class WrapFactory
{
//制造盒子的方法
public Box WrapProduct(Func<Product> getProduct)
{
//实例一个盒子
Box box = new Box();
//左边为产品类变量,右边为委托进来的方法执行
Product product = getProduct.Invoke();
box.product = product;
return box;
}
}
//产品加工厂类
class ProductFactory
{
//创造披萨的方法
public Product MakePizza()
{
//实例一个产品,产品名为pizza
Product product = new Product();
product.Name="Pizza";
return product;
}
//创造车的方法
public Product MakeToyCar()
{
//实例一个产品,产品名为车
Product product = new Product();
product.Name = "Toy Car";
return product;
}
}
}
回调方法
回调方法,通过委托类型参数传进主调方法,再调入被调方法(可以调用可以不调用,可以在需要的时候调用)。
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace NamespaceEncasement
{
class Program
{
static void Main(string[] args)
{
ProductFactory productFactory = new ProductFactory();
WrapFactory wrapFactory = new WrapFactory();
Func<Product> func1 = new Func<Product>(productFactory.MakePizza) ;
Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);
Logger logger = new Logger();
Action<Product> log = new Action<Product>(logger.Log);
Box box1 = wrapFactory.WrapProduct(func1,log);
Box box2 = wrapFactory.WrapProduct(func2,log);
Console.WriteLine(box1.product.Name);
Console.WriteLine(box2.product.Name);
Console.ReadKey();
}
}
class Logger
{
public void Log(Product product)
{
Console.WriteLine("Product{0} created at {1}.Price is {2}", product.Name,DateTime.UtcNow,product.Price);
}
}
class Product
{
public double Price { get; set; }
public string Name { get; set; }
}
class Box
{
public Product product { get; set; }
}
/// <summary>
/// 模板方法
/// </summary>
class WrapFactory
{
public Box WrapProduct(Func<Product> getProduct,Action<Product>logCallback)
{
Box box = new Box();
Product product = getProduct.Invoke();
if (product.Price >= 50)
{
logCallback(product);
}
box.product = product;
return box;
}
}
class ProductFactory
{
public Product MakePizza()
{
Product product = new Product();
product.Name="Pizza";
product.Price = 12;
return product;
}
public Product MakeToyCar()
{
Product product = new Product();
product.Name = "Toy Car";
product.Price = 100;
return product;
}
}
}
不管是回调方法还是模板方法,都是用委托类型的参数封装一个外部的方法,然后通过外部传进内部,再进行间接调用。
线程
接口替代委托
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace NamespaceEncasement
{
class Program
{
static void Main(string[] args)
{
IProductFactory pizzayFactory = new PizzaFactory();
IProductFactory toyCatFactory = new ToyCarFacoty();
WrapFactory wrapFactory = new WrapFactory();
Box box1 = wrapFactory.WrapProduct(pizzayFactory);
Box box2 = wrapFactory.WrapProduct(toyCatFactory);
Console.WriteLine(box1.product.Name);
Console.WriteLine(box2.product.Name);
Console.ReadKey();
}
}
class Logger
{
public void Log(Product product)
{
Console.WriteLine("Product{0} created at {1}.Price is {2}", product.Name,DateTime.UtcNow,product.Price);
}
}
interface IProductFactory
{
Product Make();
}
class PizzaFactory : IProductFactory
{
public Product Make()
{
Product product = new Product();
product.Name = "Pizza";
product.Price = 12;
return product;
}
}
class ToyCarFacoty : IProductFactory
{
public Product Make()
{
Product product = new Product();
product.Name = "Toy Car";
product.Price = 100;
return product;
}
}
class Product
{
public double Price { get; set; }
public string Name { get; set; }
}
class Box
{
public Product product { get; set; }
}
/// <summary>
/// 模板方法
/// </summary>
class WrapFactory
{
public Box WrapProduct(IProductFactory productFactory)
{
Box box = new Box();
Product product = productFactory.Make();
box.product = product;
return box;
}
}
}
}