我正面临一个小困境。
我需要在许多类型的实例上重复调用给定的方法,这些实例可能存在也可能不存在。因为对于任何给定的实例,方法的结果永远不会改变,所以我将缓存其返回值以供将来使用,以便减少开销并在后续调用中尽早返回,但实际完成工作的部分仍然需要调用方法 - 即-MAY-未存在:
var method = Context.Parent.GetType().GetMethod("typeHint");
if (method == null)
{
token = null;
_hasTypeHint = false;
return false;
}
var hint = ((dynamic)Context.Parent).typeHint() as VBAParser.TypeHintContext;
token = hint == null ? null : hint.GetText();
return hint != null;
捕获/处理RuntimeBinderException
是一个主要的性能瓶颈,因此我决定在调用之前反思有问题的类型,然后再发现该方法是否存在。
Context.Parent
的特定类型在编译时是未知的,并且可能的运行时类型不共享具有我正在寻找的typeHint()
方法的公共接口:我需要要么调用反射的成员,要么强制转换为dynamic
并直接调用它。
我的提交信息如下:
通过反映上下文类型来找到要使用的方法,从而消除了RuntimeBinderException的可能性。 保持(动态)强制转换因为被认为比反映调用更便宜 ..但可能是错误的。
哪一个产生的开销最小,更重要的是,为什么?
答案 0 :(得分:1)
嗯,我很好奇所以我写了一个小程序来测试:
RelativeLayout
使用不同的 var sw = new Stopwatch();
int loopLimit = 10000000;
object hint1;
sw.Start();
for( var i = 0; i < loopLimit; i++ )
hint1 = ( ( dynamic )theObject ).ToString();
sw.Stop();
Console.WriteLine( "dynamic time: {0}", sw.ElapsedMilliseconds );
sw.Restart();
for( var i = 0; i < loopLimit; i++ )
hint1 = method.Invoke( theObject, null );
sw.Stop();
Console.WriteLine( "invoke time: {0}", sw.ElapsedMilliseconds );
Console.ReadLine();
值,您会发现相对较少的来电loopLimit
更快。当您增加Invoke
时,动态调用会赶上,然后变得更快。为什么?因为动态调用会缓存执行操作所需的表达式树。在这种情况下,只创建了一个表达式树,因为我没有更改loopLimit
(在调用站点,每个对象类型只有一个表达式树)。
所以,长话短说,如果您只调用了几千次,或者如果您要测试和调用各种各样的对象类型,则表达式树创建将会破坏您的性能并theObject
会更好。如果对象可以是少数类型中的一种,并且您的方法被调用了数百万次,那么使用Invoke
调用可能会更好。
根据您的具体情况使用数字。我的猜测是你会选择dynamic
。
答案 1 :(得分:0)
不确定这是否适合你......
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
public class Purchase : MonoBehaviour,IPointerClickHandler
{
public GameObject purchasePanel;
public GameObject panelPosition;
public void OnPointerClick (PointerEventData eventData)
{
GameObject instantiatedPurchase = Instantiate(purchasePanel, panelPosition.transform.position,panelPosition.transform.rotation) as GameObject;
instantiatedPurchase.transform.SetParent(panelPosition.transform);
}