首页 > 编程语言 >C#学习笔记-委托

C#学习笔记-委托

时间:2024-05-15 20:31:57浏览次数:11  
标签:Product 委托 C# product 笔记 class int new public

委托

  委托类似于C/C++中的函数指针。委托存储对方法的引用,可以按照某些约束指向目标方法,间接地调用这些方法。

// C
#include<stdio.h>

typedef int (*Calc)(int x, int y);

int Add(int x, int y) {
	return x + y;
}

int Sub(int x, int y) {
	return x - y;
}

int main() {
	int x = 100;
	int y = 200;
	int res = 0;

	Calc funcPoint1 = &Add;

	res = funcPoint1(x, y); //间接调用,通过函数指针调用函数
	printf("%d + %d = %d\n", x, y, res);

	res = Sub(x, y); //直接调用,通过函数名调用函数
	printf("%d - %d = %d\n", x, y, res);
}
//C#
class Program
{
    static void Main(string[] args)
    {
        //使用Action委托
        Calculator calculator = new Calculator();
        Action action = new Action(calculator.Report);
        calculator.Report();
        action();

        //使用Func委托
        Func<int, int, int> func1 = new Func<int, int, int>(calculator.Add);
        Func<int, int, int> func2 = new Func<int, int, int>(calculator.Sub);

        Console.WriteLine(func1(1,2));
        Console.WriteLine(func2(1,2));
    }
}

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

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

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

  委托是一种类,所以委托也是一种数据类型。但是和类的声明方式不同,委托的声明格式更像C/C++中函数指针的声明格式。声明的位置应该在名称空间中(在类中声明,委托会变成嵌套类)。

  委托与委托所封装的方法在类型上需要兼容:

  1、返回值的数据类型需一致;

  2、参数列表的个数和数据类型需一致(参数名可不同);

//自定义委托的声明
public delegate double Calc(double x, double y);
class Program
{
    static void Main(string[] args)
    {
        Calculator calculator = new Calculator();
        Calc cal1 = new Calc(calculator.Add);
        Calc cal2 = new Calc(calculator.Sub);
        Calc cal3 = new Calc(calculator.Mul);
        Calc cal4 = new Calc(calculator.Div);

        Console.WriteLine(cal1(1.5, 2));
        Console.WriteLine(cal2(1.5, 2));
        Console.WriteLine(cal3(1.5, 2));
        Console.WriteLine(cal4(1.5, 2));
    }
}

class Calculator
{
    public double Add(double x, double y)
    {
        return x + y;
    }

    public double Sub(double x, double y)
    {
        return x - y;
    }
    public double Mul(double x, double y)
    {
        return x * y;
    }

    public double Div(double x, double y)
    {
        return x / y;
    }
}

委托的一般使用

模板方法,“借用”指定的外部方法来产生结果。

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

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

        Console.WriteLine(box1.Product.Name);
        Console.WriteLine(box2.Product.Name);
    }
}

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

    }
}

回调方法是通过委托类型参数传进主调方法的一个被调用方法,主调方法根据情况调用这个方法。

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

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

        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;
    }
}

多播委托

  用一个委托封装多个方法。

static void Main(string[] args)
{
    Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
    Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
    Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };

    Action action1 = new Action(stu1.DoHomeWork);
    Action action2 = new Action(stu2.DoHomeWork);
    Action action3 = new Action(stu3.DoHomeWork);
    //执行的顺序按照封装方法的先后顺序 action1 -> action3 -> action 2
    action1 += action3;
    action1 += action2;
    action1();

}
}

class Student
{
    public int ID { get; set; }
    public ConsoleColor PenColor { get; set; }

    public void DoHomeWork()
    {
        for(int i = 0; i < 5; ++i)
        {
            Console.ForegroundColor = this.PenColor;
            Console.WriteLine("Student {0} doing homeWork {1} hour(s).", this.ID, i);
            Thread.Sleep(1000);
        }
    }
}

异步调用

class Program
{
    static void Main(string[] args)
    {
        Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
        Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
        Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };

        //直接同步调用
        stu1.DoHomeWork();
        stu2.DoHomeWork();
        stu3.DoHomeWork();

        Action action1 = new Action(stu1.DoHomeWork);
        Action action2 = new Action(stu2.DoHomeWork);
        Action action3 = new Action(stu3.DoHomeWork);

        //多播委托的间接同步调用
        action1 += action2;
        action1 += action3;
        action1();

        //使用委托实现间接异步调用
        action1.BeginInvoke(null, null);
        action2.BeginInvoke(null, null);
        action3.BeginInvoke(null, null);

        //显式异步调用
        Thread thread1 = new Thread(new ThreadStart(stu1.DoHomeWork));
        Thread thread2 = new Thread(new ThreadStart(stu2.DoHomeWork));
        Thread thread3 = new Thread(new ThreadStart(stu3.DoHomeWork));

        thread1.Start();
        thread2.Start();
        thread3.Start();

        Task task1 = new Task(action1);
        Task task2 = new Task(action2);
        Task task3 = new Task(action3);

        task1.Start();
        task2.Start();
        task3.Start();


        for (int i = 0; i < 10; ++i)
        {
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("Main thread {0}.", i);
            Thread.Sleep(1000);
        }
    }
}

class Student
{
    public int ID { get; set; }
    public ConsoleColor PenColor { get; set; }

    public void DoHomeWork()
    {
        for(int i = 0; i < 5; ++i)
        {
            Console.ForegroundColor = this.PenColor;
            Console.WriteLine("Student {0} doing homeWork {1} hour(s).", this.ID, i);
            Thread.Sleep(1000);
        }
    }
}

可以使用接口(Interface)取代委托。

class Program
{
    static void Main(string[] args)
    {
        IProductFactory pizzaFactory = new PizzaFactory();
        IProductFactory toyCarFactory = new ToyCarFactory();
        WrapFactory wrapFactory = new WrapFactory();

        Box box1 = wrapFactory.WrapProduct(pizzaFactory);
        Box box2 = wrapFactory.WrapProduct(toyCarFactory);

        Console.WriteLine(box1.Product.Name);
        Console.WriteLine(box2.Product.Name);
    }
}

interface IProductFactory
{
    Product Make();
}

class PizzaFactory : IProductFactory
    {
        public Product Make()
        {
            Product product = new Product();
            product.Name = "Pizza";
            return product;
        }
    }

    class ToyCarFactory : IProductFactory
    {
        public Product Make()
        {
            Product product = new Product();
            product.Name = "Toy Car";
            return product;
        }
    }

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

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


class WrapFactory
{
    public Box WrapProduct(IProductFactory productFactory)
    {
        Box box = new Box();
        Product product = productFactory.Make();
        box.Product = product;
        return box;
    }
}

标签:Product,委托,C#,product,笔记,class,int,new,public
From: https://www.cnblogs.com/owmt/p/18176122

相关文章

  • mac指定虚拟网卡访问某个域名
    通过ifconfig命令,一般会显示很多个虚拟网卡(冒号左边的就是网卡名)。有些情况下,只能特定的网卡才能访问网站,所以需要指定网卡去访问。指定网卡访问的命令(新增路由表)sudorouteadd-host目标地址-interface网卡名删除指定网卡访问网站命令sudoroutedel-net目标地址......
  • Nsight compute权限访问受阻问题
    在非root或sudoer用户下进行ncu命令分析cuda程序时,会报错RR_NVGPUCTRPERMTheuserrunning<tool_name/application_name>doesnothavepermissiontoaccessNVIDIAGPUPerformanceCountersonthetargetdevice.此时可以选择申请root权限或在docker内进行性能分析,目前还......
  • pytorch调试时CUDA报错,如何精确定位
    由于pytorch的python语句执行和CUDA后端实际上是异步执行的,所以当CUDAruntime报错时,并不一定能正确地反映在python抛出的错误语句中,因此,可以添加一个环境变量来实现:CUDA_LAUNCH_BLOCKING=1这里再补充一些关于cuda和pytorch异步执行的知识,当你写了一句torch.mm(X,Y)时,实际上......
  • read() 和revc()
    `read()`和`recv()`函数都是用于从套接字(socket)中接收数据的函数,但它们在不同的情况下使用略有不同,主要区别在于:1.**函数签名和参数**:-`read()`函数是POSIX标准定义的,它的函数签名通常是`ssize_tread(intfd,void*buf,size_tcount)`,其中`fd`是文件描述符,`buf`......
  • MapReduce思考问题
    MapReduce思考问题(每一个都算面试题)Q1、map数量数越多越好吗?不是,因为产生map任务是需要资源和时间,map任务越多,占用的资源和时间越多Q2、hdfs是否适合存储小文件(MR角度出发)不适合,小文件一多,意味着block块就多了,切片split也就多了,这样产生的map数量也就多了起来Q3、split和map......
  • [HDCTF 2023]YamiYami python中的另一种反序列化--yaml
    今天做了到新颖的题,关于python中的yaml反序列化的题目,直接上题吧。发现第一个链接的参数是?url=XXXX,一眼利用点。嗯?直接出了flag,应该是非预期解。再看看有app.py,那就试试。发现app.*被过滤了,二次编码绕过试试。点击查看代码@app.route('/')defindex():session['pas......
  • caddy自动https服务器中间件
    Caddy是一个功能丰富的开源Web服务器,具有自动HTTPS的能力。它被设计为易于使用,并具有现代化的功能和配置选项。以下是Caddy的一些主要特点:自动HTTPS: Caddy可以自动为您的网站提供HTTPS支持,而不需要复杂的配置。它使用Let'sEncrypt来自动获取和管理SSL/TLS证书......
  • msvc 获取c++类内存布局 /d1 reportAllClassLayout
     visualstudio配置获取所有类内存布局/d1reportAllClassLayout或者指定类/d1reportSingleClassLayoutXXXclass  编译时输出:     ps:https://www.openrce.org/articles/full_view/23   【原文地址】https://blog.csdn.net/qq_29542611/article......
  • 「ABC353」Yet Another Sigma Problem
    题目字典树做法(用时187ms)#include<cstdio>#include<ctype.h>constintN=3e5+10;intn;longlongans;inttrans[N][26],cnt[N];inttot;chars[N];template<classT>voidread(T&x){ charc=getchar(); while(!isdigit(c))c=getchar()......
  • epoll、poll、select
    `epoll`、`select`和`poll`都是在Linux系统中用于实现I/O多路复用的机制,它们都能够实现在多个文件描述符上进行非阻塞的I/O操作,并在有I/O事件发生时通知应用程序。以下是它们的一些比较:1.**`select`**:-`select`是Unix系统最早的一种多路复用机制之一。-它......