【Unity项目实践】委托
  EFTJ6596AiAP 2023年11月02日 79 0

什么是委托?

函数指针的升级版,间接实现

数据和算法本质上都是地址

直接调用:通过函数的名字进行调用,直接获得函数所在地址并开始执行

间接实现:通过读取函数指针存储的函数所在地址并开始执行

Java不允许直接访问地址

Action和Func都是委托的一种


Action委托

Action是返回值和参数列表都为空的,只有符合这个条件的才可以用Action

Action action = new Action(calculator.Report);//这里只需要方法名,不需要在后面加圆括号
calculator.Report();//直接调用
action.Invoke();//间接调用
action();//间接调用的简写版


Func委托

泛型委托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);

int x=100;
int y=200;

int z=0;
z = func1.Invoke(x, y);
z = func1(x, y);//间接调用的简写版本


声明委托

委托是一种类,类一种引用类型的数据类型。

声明格式

和类层级平行,需要在类的外面声明。

//声明ming
public delegate double Calc(double x, double y);//类型约束

//实例化
Calc calc1= new Calc(calculator.Add);//实例化的时候括号中填写方法名,其中的方法需要和声明的委托中的一致

//调用
c= calc1.Invoke();
c= calc1;


委托声明的注意点

委托和封装的方法必须类型兼容,也就是返回值类型和参数列表一致

委托的声明需要放在名称空间中,和类同一个级别。如果在类声明,就成为了嵌套类


委托的一般使用

把方法当作参数进行传递,动态调用方法。

模板方法

相当于填空题

位于代码中部

有返回值


回调方法

相当于流水线

位于代码尾部

无返回值


以下是代码例子:

Func<>的尖括号中包含参数和返回值,其中参数不是必须的,返回值是必须的。所以如果尖括号中只有一个值的时候,是返回值。

【Unity项目实践】委托_方法名

A Func delegate type can include 0 to 16 input parameters of different types. However, it must include an out parameter for the result. For example, the following Func delegate doesn't have any input parameter, and it includes only an out parameter.

参考:​https://www.tutorialsteacher.com/csharp/csharp-func-delegate​

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ComputingWithCSharp
{
public 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.ReadLine();
}
}

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,否则默认是internal的,类外面不可以访问
public double price { get; set; }
}

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

class WrapFactory
{
public Box WrapProduct(Func<Product> getProduct, Action<Product> log)//参数列表是Func<Product>
{
Box box = new Box();
Product product = getProduct.Invoke();
if (product.price >= 50)
{
log(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 = "ToyCar";
product.price = 100;
return product;
}
}

}


注意:

委托是一种方法级别的耦合

注意不要把委托回调、异步调用


委托的高级使用

多播委托:一个委托内封装的不只有一个方法


----------------------------------------------后续学到了再来补---------------------------------------------



数据model和表现层分开

用property来写数据model

public static calss CounterModel{
private static int mCount =0;
public static Action<int> OnCountChanged;

public static int Count{
get {return mCount;}
set { if (value != mCount){mCount = value;}}
}
}


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

EFTJ6596AiAP