在C#中动态关键字性能

本文关键字:关键字 性能 动态 | 更新日期: 2023-09-27 17:57:27

如果使用动态关键字&我们给它分配了一些类型,编译器是否执行装箱/取消装箱操作?例如

dynamic myInstance=null;
object key="BankProject.Payment";
Type myType=ServiceCashe.GetType(key);//get desire type from cache...
myInstance=Activator.CreateInstance(myType); //instanciate myType

在C#中动态关键字性能

除非是值类型,否则不会进行装箱操作,但在您使用的代码示例中,无论如何都没有真正使用动态类型。到目前为止,您的代码相当于:

object key = "BankProject.Payment";
Type myType = ServiceCashe.GetType(key);
object myInstance = Activator.CreateInstance(myType);

只有当您执行动态成员访问(例如myInstance.SomeMethod())时,动态键入才会真正生效。通常避免这种情况的方法是使您正在获取的所有类型动态地实现一些接口:

object key = "BankProject.Payment";
Type myType = ServiceCashe.GetType(key);
IPayment myInstance = (IPayment) Activator.CreateInstance(myType);
myInstance.SomeMethodInInterface();

然后,只有"动态"部分正在创建实例,然后在强制转换中检查执行时间。

和往常一样,如果你有绩效问题,你应该在现实的情况下对照明确的目标来衡量它们。即使确实执行了装箱和拆箱操作,我们也不知道在您的环境中这是否是的重大成本。(碰巧,根据我的经验,装箱和拆箱比Activator.CreateInstance便宜得多…)

为了参考,如果您创建方法:

static void Test()
{
    dynamic myInstance = null;
    object key = "BankProject.Payment";
    Type myType = typeof(SomeClass);
    myInstance = Activator.CreateInstance(myType);
    int result = myInstance.SomeMethod();
}

这将在内部翻译成类似(在ILSpy中反编译):

private static void Test()
{
    Type myType = typeof(SomeClass);
    object myInstance = Activator.CreateInstance(myType);
    if (Program.<Test>o__SiteContainer0.<>p__Site1 == null)
    {
        Program.<Test>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, int>>.Create(Binder.Convert(CSharpBinderFlags.None, typeof(int), typeof(Program)));
    }
    Func<CallSite, object, int> arg_AA_0 = Program.<Test>o__SiteContainer0.<>p__Site1.Target;
    CallSite arg_AA_1 = Program.<Test>o__SiteContainer0.<>p__Site1;
    if (Program.<Test>o__SiteContainer0.<>p__Site2 == null)
    {
        Program.<Test>o__SiteContainer0.<>p__Site2 = CallSite<Func<CallSite, object, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.None, "SomeMethod", null, typeof(Program), new CSharpArgumentInfo[]
        {
            CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
        }));
    }
    int result = arg_AA_0(arg_AA_1, Program.<Test>o__SiteContainer0.<>p__Site2.Target(Program.<Test>o__SiteContainer0.<>p__Site2, myInstance));
}

因此,正如您所看到的,所涉及的代码比您第一眼所能想到的要多得多。