目录
目录基础介绍
在c#中委托是一个类型安全的,面向对象的函数指针。
委托的优点是它允许程序员在运行时动态地选择所需要调用的方法。
本文将从Unity的源码出发,分析委托的作用。
为什么用委托?
委托常用的场景有:
- 回调函数:可以将一个委托作为参数传递给另一个函数,这样你就可以在运行时动态决定哪个方法应该被调用。
- 事件处理:委托可以用于实现事件,在 C# 中,事件是一种特殊类型的委托,可以让多个对象监听并响应特定事件。特别适合用来作UI相应后的操作。
- 多线程编程:可以使用委托来在多线程中调用函数。
- 异步编程:可以使用委托来在异步方式中调用函数。
源码中的委托
针对委托的常用场景,找了下Unity源码中的例子。
用于回调函数
排序方法就是个很好的例子。
传一个匿名方法(a,b)={return a>b}就是一个委托。
下面是Unity源码中使用委托用于回调函数的例子:
// 这段代码来自UnityEditorInternal.DopeLine
m_Keys.Sort((a, b) => a.time.CompareTo(b.time));
// 这段代码出自UnityEditor.MaterialEditor
matched[i].Sort((s2, s1) =>
{
var order = (int)((s2 as ShaderDropdownItem)?.fullName.Count(c => c == '/') - (s1 as ShaderDropdownItem)?.fullName.Count(c => c == '/'));
if (order == 0)
order = s2.name.CompareTo(s1.name);
return order;
});
用于事件处理
EditorApplictaion.projectWindowItemCallback演示了委托用于事件处理
public static EditorApplication.ProjectWindowItemCallback 是Project 窗口中每个可见列表项的 OnGUI 事件的委托。
委托在UnityEditor.EditorApplication.cs里被定义:
public sealed partial class EditorApplication{
// Delegate to be called for every visible list item in the ProjectWindow on every OnGUI event.
public delegate void ProjectWindowItemCallback(string guid, Rect selectionRect);
// Delegate for OnGUI events for every visible list item in the ProjectWindow.
public static ProjectWindowItemCallback projectWindowItemOnGUI;
}
委托对象在UnityEditor.ProjectBrowser里被调用:
void OnGUIAssetCallback(int instanceID, Rect rect)
{
// User hook for rendering stuff on top of assets
if (EditorApplication.projectWindowItemOnGUI != null)
{
string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(instanceID));
EditorApplication.projectWindowItemOnGUI(guid, rect);
}
if (EditorApplication.projectWindowItemInstanceOnGUI != null)
{
EditorApplication.projectWindowItemInstanceOnGUI(instanceID, rect);
}
}
可以通过给委托添加方法来实现代码的触发,如:
//这是一段伪代码,展示了如何添加委托
{
static ShowFileExtensions()
{
EditorApplication.projectWindowItemOnGUI += ProjectWindowItemOnGUI;
}
private static void ProjectWindowItemOnGUI(string guid, Rect rect)
{
//当Project 窗口中每个可见列表项的 OnGUI 事件发生时,这里的代码会执行
}
}
组合委托是个好功能,可以更简单地组织代码,并且提高程序的可重用性。
可以使用组合委托来组织多个事件处理程序,如一个按钮点击,触发多个其他函数。
UnityEditor.ProjectBrowser里使用了组合委托,可以方便地添加调试逻辑而不与其他代码耦合:
// Keep for debugging
//EditorApplication.projectWindowItemOnGUI += TestProjectItemOverlayCallback;
其他知识
- 虽然委托类型声明看上去和方法的生命一样,但它不需要再类内部进行声明,因为它是类型声明。
namespace UnityEngine.Events
{
// 可以在类外面声明委托
public delegate void UnityAction<T0>(T0 arg0);
[Serializable]
public class UnityEvent<T0> : UnityEventBase
{
}
}
- 在使用+=和-=运算符,其实是创建了一个新的委托,这个委托持有委托组合的引用。
- 调用带返回值的委托,最后一个方法的返回值就是委托的返回值,中间其他方法的返回值都会被忽略。
- 调用带有引用参数的委托,参数的新值(不是初始值)会传给下一个方法。
- 委托的几种创建方式:
//基础语法
MyDelegate del = new MyDelegate(obj.TestMethod));
del();
//快捷语法
MyDelegate del2 = (obj.TestMethod);
del2();
//匿名方法(C#2.0引入)
MyDelegate del3 = delegate ()
{
return;
};
del3();
//lambda表达式(C#3.0引入)
MyDelegate del4 = () =>
{
return;
};
del4();
//lambda,不加括号也行
int x = 1;
MyDelegate2 del5 = x => { return; };
标签:projectWindowItemOnGUI,return,委托,EditorApplication,Unity,源码,public
From: https://www.cnblogs.com/wenqu/p/17041466.html