Unity学前C#:委托详解

这篇具有很好参考价值的文章主要介绍了Unity学前C#:委托详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.什么是委托

字面意思就是:这件事情我不亲自去做,而是委托别人去做
C#中的委托有点类似c/c++中的函数指针,但是C#中的委托就可以看作是函数指针的升级版

以下是c/c++的函数指针实例

#include<bits/stdc++.h>
using namespace std;

int (*Cal)(int a, int b);
//或者用typedef int (*Cal)将Cal定义为一种数据类型
int Add(int x, int y)
{
	cout << "x+y=" << x + y << endl;
	return x + y;
}

int main()
{
	Cal = Add;//函数指针的调用
	int x = 100;
	int y = 100;
	int c = Cal(x, y);
	return 0;
}

 先理解一个概念:一切皆地址

在计算机中所有的程序以及数据的存储都是有地址可循的,计算机组成原理就解释了程序的执行过程(将程序中的一条一条指令写入连续的内存中,并且用第一条指令的地址来表示它),所以函数和数据的区别就是,函数是寻找函数的地址,而数据是寻找数据的地址

直接调用:通过函数名调用,CPU通过函数名直接找到函数所在的首地址,然后调用函数

间接调用:通过函数指针调用,CPU先通过函数指针找到函数所在的地址然后调用函数

二.C#中的委托

C#中自带的委托

Fun<>:代参数的委托,一共有17中定义

Action :不带参数的委托

class Programme
{
    static void Main(string[] args)
    {
        Complex complex = new Complex();
        Action action = new Action(complex.PrintInfo);//注意这里只是要获得函数的地址名字所以不用加括号,加括号就是表示调用该函数了
        action();
        Func<int, int, int> fun = new Func<int, int, int>(complex.Add);
        int test;
        test = fun(1, 2);
        Console.WriteLine(test);
    }
}

class Complex
{
    public void PrintInfo()
    {
        Console.WriteLine("PrintInfo has been used");
    }

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

/*
 * 输出结果
 * PrintInfo has been used
    3
 */

 自定义委托

delegate关键字

从某种意义上来讲,委托也可以算是一种类,所以在定义的时候应该与类同一个级别,也就是写在命名空间下面

delegate int Cal(int x, int b);
class Programme
{
    static void Main(string[] args)
    {
        Cal add = new Cal(Calculate.ADD);
        Cal cut = new Cal(Calculate.Cut);
        Cal mutiply = new Cal(Calculate.Mutiply);
        Cal except= new Cal(Calculate.Except);
        int x = 100;
        int y = 200;
        try
        {
            Console.WriteLine(add(x, y));
            Console.WriteLine(cut(x, y));
            Console.WriteLine(mutiply(x, y));
            Console.WriteLine(except(x, 0));
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

class Calculate
{
    public static int ADD(int x,int y)
    {
        return x + y;
    }

    public static int Cut(int x,int y)
    {
        return x - y;
    }

    public static int Mutiply(int x,int y)
    {
        return x * y;
    }

    public static int Except(int x,int y)
    {
        if (y == 0)
            throw new Exception("y cannot be zero");
        return x / y;
    }
}

三.委托方法的应用 

 1.模板方法

便于函数重用,有利于减少bug,降低bug的修复成本

class Programme
{
    static void Main(string[] args)
    {
        ProductFactory factory = new ProductFactory();
        Func<Product> fun1 = factory.MakingPizza;
        Func<Product> fun2 = factory.MakingToycar;
        WarpFactory warpFactory = new WarpFactory();
        Console.WriteLine(warpFactory.WarpProduct(fun1).Product.Name);
        Console.WriteLine(warpFactory.WarpProduct(fun2).Product.Name);
    }
}

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

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

class WarpFactory
{
    public Box WarpProduct(Func<Product> fun)
    {
        Product product =fun();//或者fun.invoke
        Box box = new Box();
        box.Product = product;
        return box;
    }
}

class ProductFactory
{
    public Product MakingToycar()
    {
        Product product = new Product();
        product.Name = "Toy car";
        return product;
    }

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

2.回调方法 

回调的理解:假如你是公司的老板,你收到了很多实习生投递的简历,但是你要根据你的需求在合适的实践选择相应的员工

   class Programme
   {
       static void Main(string[] args)
       {
           ProductFactory factory = new ProductFactory();
           Func<Product> fun1 = factory.MakingPizza;
           Func<Product> fun2 = factory.MakingToycar;
           WarpFactory warpFactory = new WarpFactory();
           Logger logger = new Logger();
           Action<Product> action = logger.logCallBack;
           Console.WriteLine(warpFactory.WarpProduct(fun1,action).Product.Name);
           Console.WriteLine(warpFactory.WarpProduct(fun2,action).Product.Name);
       }
   }

   class Logger
   {
       public void logCallBack(Product product)
       {
           Console.WriteLine("{0} has been warped at {1} and the price is {2}", product.Name, DateTime.UtcNow,product.Price);
       }
   }

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

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

   class WarpFactory
   {
       public Box WarpProduct(Func<Product> fun,Action<Product> LoggerCallBack)
       {
           Product product =fun();//或者fun.invoke
           Box box = new Box();
           box.Product = product;
           if(product.Price>50)
           {
               LoggerCallBack(product);
           }
           return box;
       }
   }

   class ProductFactory
   {
       public Product MakingToycar()
       {
           Product product = new Product();
           product.Name = "Toy car";
           product.Price = 100;
           return product;
       }

       public Product MakingPizza()
       {
           Product product = new Product();
           product.Name = "Pizza";
           product.Price = 10;
           return product;
       }
   }

 总结:难精通+易使用,在使用的时候还是要三思

四.委托的高级使用

多播(multicast)委托

一个委托内封装着不止一个方法

执行的顺序就是按照封装的顺序执行方法

class Programme
{
    static void Main(string[] args)
    {
        Student stu1 = new Student() { ID = 1,Color = ConsoleColor.Red};
        Student stu2 = new Student() { ID = 2, Color = ConsoleColor.Green };
        Student stu3 = new Student() { ID = 3,Color = ConsoleColor.Blue};
        Action action = stu1.DoHomeWord;
        Action action2 = stu2.DoHomeWord;
        Action action3 = stu3.DoHomeWord;
        action += action2;
        action += action3;
        action();
        
    }
}

class Student
{
    public int ID { get; set; }
    public ConsoleColor Color { get; set; }
    public void DoHomeWord()
    {
        for(int i=0;i<5;i++)
        {
            Console.ForegroundColor = Color;
            Console.WriteLine("{0} is Do Homework {1}", ID, i);
            Thread.Sleep(1000);//多线程,就是所在的线程每次执行到这里都休息一秒
        }
    }
}

 隐式异步调用

同步:你做完了,我接着做,相当于是流水线

Unity学前C#:委托详解,c#,开发语言

程序开始执行的时候都会有一个主线程,其余的都叫做分线程,上图红线的就是主线程 ,其他颜色的线代表方法,不难看出每个方法执行的顺序是依次进行的,所以叫同步

异步:两个人互不相干

Unity学前C#:委托详解,c#,开发语言

Unity学前C#:委托详解,c#,开发语言 

 隐式异步调用

//将上述代码的action()改成如下代码即可显示为异步调用
action.BeginInvoke(null,null);
action2.BeginInvoke(null,null);
action3.BeginInvoke(null,null);

 Unity学前C#:委托详解,c#,开发语言

可以发现显示的颜色并不符合代码的要求:

因为多个线程都在抢占同一个资源,这样就会导致资源抢夺,所以解决的办法就是给线程加锁,这是以后的内容了 

显示异步调用 

Task task1 = new Task(stu1.DoHomeWord);
Task task2 = new Task(stu2.DoHomeWord);
Task task3 = new Task(stu3.DoHomeWord);
task1.Start();
task2.Start();
task3.Start();


 

Thread thread1 = new Thread(new ThreadStart(action));
Thread thread2 = new Thread(new ThreadStart(action2));
Thread thread3 = new Thread(new ThreadStart(action3));
thread1.Start();
thread2.Start();
thread3.Start();

Unity学前C#:委托详解,c#,开发语言 

也出现了和隐式一样的资源抢夺情况

 五.拓展:Interface

本来一位接口是一个知识点,后来发现和c++中的纯虚函数相似,

interface可以代替委托

class Programme
{
    static void Main(string[] args)
    {
        IProductFactory toy = new ToyFactory();
        IProductFactory pizza = new PizzaFactory();
        WarpFactory warpFactory = new WarpFactory();
        Console.WriteLine(warpFactory.WarpProduct(toy).Product.Name);
        Console.WriteLine(warpFactory.WarpProduct(pizza).Product.Name);
    }
}

interface IProductFactory
{
    Product Make();
}

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

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

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

class WarpFactory
{
    public Box WarpProduct(IProductFactory ipf)
    {
        Product product = ipf.Make();//或者fun.invoke
        Box box = new Box();
        box.Product = product;
        return box;
    }
}

总结

 委托的使用要非常谨慎,所以在c#中可以合并Interface一并使用,java之所以在没有委托的情况下能发展就是用了Interface实现了委托的功能

 文章来源地址https://www.toymoban.com/news/detail-841511.html

 

到了这里,关于Unity学前C#:委托详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C#学习笔记】委托与事件 (从观察者模式看C#的委托与事件)

    转载请注明出处:🔗https://blog.csdn.net/weixin_44013533/article/details/134655722 作者:CSDN@|Ringleader| 主要参考: 委托(C# 编程指南) 事件介绍 C# 中的委托和事件简介 Delegate 类 Exploring the Observer Design Pattern微软技术文章翻译 委托是一种 引用类型 ,表示对具有特定参数列表和返回类型

    2024年02月04日
    浏览(50)
  • C#之委托

    目录 一、简介 (一)概述 (二)类与委托 二、声明委托 三、使用委托 (一)创建委托对象 (二)使用委托 四、简单的委托示例 五、Action[T]和Func[T]委托 六、多播委托 七、匿名方法         委托时寻址方法的.NET版本。在C++中,函数指针只不过是一个指向内存位置的指

    2024年01月18日
    浏览(37)
  • C#基础--委托

    C#基础–委托 简单说它就是一个能把方法当参数传递的对象,而且还知道怎么调用这个方法,同时也是粒度更小的“接口”(约束了指向方法的签名) 跟方法有点类似,有参数,返回值,访问修饰符+ delegate 委托的本质是一个类,继承自一个特殊类 MulticastDelegate ,我们自己在

    2024年02月16日
    浏览(43)
  • C# 常量 结构体 委托

    常量名命名一般使用大写字母 开发一个游戏,游戏角色有法师(Mage)、射手(Archer)、刺客(Assassin)、坦克(Tank)、铺助(Support)、战士(Warrior),等不同类型。 ❓如何存储游戏角色 使用 int 类型 :创建一套规则,提前为各个类型角色绑定一个数字标识 使用枚举类型 什么是枚举类型?

    2024年02月02日
    浏览(33)
  • C#——委托

    什么是委托        C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。 声明委托          委托声明决定了可由该委托引用的方法。委托可指向一个与其具有相同标签的方法。  

    2023年04月15日
    浏览(29)
  • C#编程-实现委托

    委托是可以存储对方法的引用的对象。在C#中,委托允许您动态地改变类中方法的引用。 考虑咖啡售货机的示例,它配置不同口味的咖啡,例如卡布奇诺咖啡和黑咖啡。在选择所需口味的咖啡时,售货机决定混合各种成分,例如奶粉、咖啡粉、热水、卡布奇诺咖啡粉。所有的

    2024年02月02日
    浏览(36)
  • C#的Func(委托)

    在 C# 中,Func 是一个泛型委托类型,用于表示一个具有返回值的方法或 lambda 表达式。 Func 可以接受 0~16 个输入参数,其最后一个泛型参数表示返回值类型。例如,Func 表示一个不接受参数,返回整数类型的方法。 以下是一个 Func 的简单例子: 在上面的例子中,我们创建了一

    2024年02月15日
    浏览(46)
  • c# 事件与委托

    //在C#中, 事件是一种特殊的委托 ,它允许对象通知其他对象发生了某个特定的事件。 //事件通常用于GUI应用程序中,例如当用户单击按钮时,按钮控件会引发Click事件, //然后其他对象可以订阅该事件并执行相应的操作。 //以下是一个简单的示例,演示如何在C#中使用事件和

    2024年02月06日
    浏览(42)
  • 委托与事件(一)——C#版本

      委托是对 函数的封装 ,可以当作给方法的特征指定一个名称。而事件则是 委托的一种特殊形式 ,当发生有意义的事情时,事件对象处理通知过程。   委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有 完全相同的行为 。   用例子来说明为

    2023年04月09日
    浏览(46)
  • C#委托和事件简单复习

    太久没用了,简单的复习一下 快速过一遍语法使用 1.定义一个委托类型 只需要在声明的前面加上delegate,其他的就跟声明一个方法(函数)类似 2.使用刚刚声明的委托 需要定义一个返回值跟参数与我们刚刚定义的委托一致 3.然后声明一个SayHello类型(委托)的变量 把

    2024年02月14日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包