一、什么是扩展方法?
扩展方法是一种C#语言提供的功能,允许我们向现有类型添加新的方法,而无需修改类型的源代码。扩展方法的优缺点如下:
二、它有什么优点?
1、不需要修改源类型的代码:使用扩展方法可以向现有类型添加新的方法,而无需修改类型的源代码。这使得我们可以对第三方库或系统类型进行扩展,而无需获取其源代码或进行修改。这可以减少代码维护的工作量和风险。
2、提高代码的可读性:使用扩展方法可以使代码更加简洁和易读。通过将通用的功能封装在扩展方法中,我们可以消除代码中的冗余和重复,从而使代码更加清晰和易于理解。
3、支持链式调用:扩展方法可以支持链式调用,使代码更加简洁和易读。通过在一个方法中返回this,我们可以使其它方法可以直接在该方法的返回值上进行调用,从而实现链式调用的效果。
三、它有什么缺点?
1、可能会引起命名冲突:由于扩展方法是静态方法,它们的名称必须是唯一的。如果我们在不同的命名空间中定义了具有相同名称和签名的扩展方法,那么在使用时可能会发生命名冲突,导致编译错误或运行时错误。
2、可能会引起误解:使用扩展方法可以使代码更加简洁和易读,但也可能会使代码更加晦涩和难以理解。如果我们在不同的代码中定义了许多扩展方法,可能会使代码难以理解和维护。
3、可能会影响性能:扩展方法是静态方法,它们的调用需要通过静态方法调用的方式进行。这可能会影响性能,特别是在频繁调用的情况下。但是,这种影响通常非常小,不会对应用程序的性能产生显著影响。
四、扩展方法就像一个人体的外骨骼
【网络图片,侵删】
1、类似于外骨骼,扩展方法可以提供一些额外的功能和支持,使得我们能够更加高效地完成任务,从而提高我们的生产力和效率。同时,扩展方法也可以使我们的代码更加简洁和易于理解,从而提高代码的可读性和可维护性。
2、然而,就像外骨骼可能会增加残疾人的负担和复杂性一样,扩展方法也可能会增加代码的复杂性和难度。如果不适当使用扩展方法,可能会引入一些新的问题和错误,从而影响程序的性能和正确性。因此,使用扩展方法时,需要谨慎权衡和选择,以充分发挥其优势并避免潜在的问题。
四、实现EventTrigger上所有事件的异步等待方法
1、实现的过程:
- 判断EventTrigger是否存在,没有则添加
- 定义一个委托MyAction
- 定义一个方法fn
- 绑定委托MyAction+=fn
- EventTrigger添加一个事件绑定,MyAction.invoke
- 等待触发
- 撤销委托绑定
- 回收资源
2、代码
public static class ExtensionMethod
{
/// <summary>
/// 物体的EventTrigger事件触发异步方法
/// </summary>
/// <param name="gameObject">要互动的物体</param>
/// <returns></returns>
public static async UniTask OnEventTriggerAsync(this GameObject gameObject, EventTriggerType eventType)
{
//添加组件
var hasEventTrigger = gameObject.GetComponent<EventTrigger>() != null;
if (!hasEventTrigger) gameObject.AddComponent<EventTrigger>();
bool triggered = false;
//委托及实例方法
Action myAction = null;
Action fn = () =>
{
triggered = true;
};
//委托绑定
myAction += fn;
//事件触发
gameObject.GetComponent<EventTrigger>().AddListener(eventType, (PointerEventData eventData) =>
{
if (myAction != null)
{
//Debug.Log("事件触发");
myAction.Invoke();
}
});
//等待事件触发
await UniTask.WaitUntil(() => triggered == true);
Debug.Log("");
//取消绑定
myAction -= fn;
//资源清理:如果代码是并发执行,可能会把别人动态添加的eventTrigger销毁掉,所以建议不销毁
//if (!hasEventTrigger) GameObject.DestroyImmediate(gameObject.GetComponent<EventTrigger>());
return;
}
}
五、测试
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.EventSystems;
public class Test : MonoBehaviour
{
public GameObject cube;
// Start is called before the first frame update
void Start()
{
WaitEvent();
}
private async UniTask WaitEvent()
{
while (true)
{
//等待拖动
await cube.OnEventTriggerAsync(EventTriggerType.Drag);
Debug.Log("拖动发生");
//等待点击
await cube.OnEventTriggerAsync(EventTriggerType.PointerClick);
Debug.Log("点击发生");
}
}
}