夜间模式暗黑模式
字体
阴影
滤镜
圆角
主题色
C# delegate 学习记录

这个要命的东西一直困扰着我,至今我也没整明白.

委托(delegate)是C++中函数指针的” 升级 “.
委托是类的一种, 定义在命名空间块中, 与其他类平行.

委托的两种简单形式

  1. Action委托
  2. Func委托

Action委托

委托无返回值的方法, 根据参数数量不同, Action<T1,……T16> 多达16个的重载.

Function委托

委托有返回值的方法, 根据参数数量不同, Func<T1,T2,T3……,Tresult>17种类型重载, T1……T16为出入参数, Tresult为返回类型.

直接调用与间接调用

class Calculator
{
    public void Report()
    {
        Console.WriteLine("I have 3 menthods.");
    }

    public int Add(int a, int b)
    {
        return a + b;
    }

    public int Sub(int a, int b)
    {
        return a - b;
    }
}

直接调用:

Calculator calculator = new Calculator();
calculator.Add(1,2);

间接调用:

Calculator calculator = new Calculator();
Func<int, int, int> func = new Func<int, int, int>(Calculator.Add);
func.Invoke(1,2);
func(1,2);
//第4行是第3行的简化, 两者意义相同, 省略Invoke是为了继承C++中的传统指针调用方法

自定义委托

delegate 返回值类型 委托名(参数列表);

委托与封装的方法必须” 类型兼容 “
即返回值类型和参数列表相同(具体参数名可以不同)

委托的一般使用

  1. 模板方法
  2. 回调(Callback)方法

模板方法

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

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

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()
    {
        Product product = new Product();
        product.Name = "Pizza";
        return product;
    }

    public Product MakeToyCar()
    {
        Product product = new Product();
        product.Name = "Toy Car";
        return product;
    }
}
ProductFactory productFactory = new ProductFactory();
WrapFactory wrapFactory = new WrapFactory();

Func<Product> func1 = new Func<Product>(productFactory.MakeToyCar);
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);

结果应该输出:
Pizza
Toy Car

模板方法的优点是固定了大部分逻辑, 使增加Product变得更加容易, 易于后期维护

回调方法

class Logger
{
    public void Log(Product product)
    {
        Console.WriteLine("Product '{0}' create at '{1}'", product, DateTime.Now);
    }
}

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();

        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;
    }
}
ProductFactory productFactory = new ProductFactory();
WrapFactory wrapFactory = new WrapFactory();

Func<Product> func1 = new Func<Product>(productFactory.MakeToyCar);
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);

结果应该输出:
Toy Car create at Time
Pizza
Toy Car

这里的Time应该是时间, 因为我没有运行所以用 Time 代替

委托的高级使用

一般使用我还没整明白, 高级使用就留在这里以后再写.

暂无评论

发送评论 编辑评论


				
上一篇
下一篇