php中文网 | cnphp.com

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 551|回复: 0

C#不同反射调用方法的性能差异

[复制链接]

3146

主题

3156

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

UID
1
威望
0
积分
7966
贡献
0
注册时间
2021-4-14
最后登录
2024-11-23
在线时间
763 小时
QQ
发表于 2022-6-29 13:06:16 | 显示全部楼层 |阅读模式
[mw_shl_code=csharp,true]using System;
using System.Diagnostics;
using System.Reflection;

namespace Walterlv.Demo
{
    public class Program
    {
        static void Main(string[] args)
        {
            // 调用的目标实例。
            var instance = new StubClass();

            // 使用反射找到的方法。
            var method = typeof(StubClass).GetMethod(nameof(StubClass.Test), new[] { typeof(int) });
            // 将反射找到的方法创建一个委托。
            var func = InstanceMethodBuilder<int, int>.CreateInstanceMethod(instance, method);

            // 跟被测方法功能一样的纯委托。
            Func<int, int> pureFunc = value => value;

            // 测试次数。
            var count = 10000000;

            // 直接调用。
            var watch = new Stopwatch();
            watch.Start();
            for (var i = 0; i < count; i++)
            {
                var result = instance.Test(5);
            }

            watch.Stop();
            Console.WriteLine($"{watch.Elapsed} - {count} 次 - 直接调用");

            // 使用同样功能的 Func 调用。
            watch.Restart();
            for (var i = 0; i < count; i++)
            {
                var result = pureFunc(5);
            }

            watch.Stop();
            Console.WriteLine($"{watch.Elapsed} - {count} 次 - 使用同样功能的 Func 调用");

            // 使用反射创建出来的委托调用。
            watch.Restart();
            for (var i = 0; i < count; i++)
            {
                var result = func(i);
            }

            watch.Stop();
            Console.WriteLine($"{watch.Elapsed} - {count} 次 - 使用反射创建出来的委托调用");

            // 使用反射得到的方法缓存调用。
            watch.Restart();
            for (var i = 0; i < count; i++)
            {
                var result = method.Invoke(instance, new object[] { 5 });
            }

            watch.Stop();
            Console.WriteLine($"{watch.Elapsed} - {count} 次 - 使用反射得到的方法缓存调用");

            // 直接使用反射调用。
            watch.Restart();
            for (var i = 0; i < count; i++)
            {
                var result = typeof(StubClass).GetMethod(nameof(StubClass.Test), new[] { typeof(int) })
                 ?.Invoke(instance, new object[] { 5 });
            }

            watch.Stop();
            Console.WriteLine($"{watch.Elapsed} - {count} 次 - 直接使用反射调用");
        }

        private class StubClass
        {
            public int Test(int i)
            {
                return i;
            }
        }
    }
    public static class InstanceMethodBuilder<T, TReturnValue>
    {
        /// <summary>
        /// 调用时就像 var result = func(t)。
        /// </summary>
        public static Func<T, TReturnValue> CreateInstanceMethod<TInstanceType>(TInstanceType instance, MethodInfo method)
        {
            if (instance == null) throw new ArgumentNullException(nameof(instance));
            if (method == null) throw new ArgumentNullException(nameof(method));

            return (Func<T, TReturnValue>)method.CreateDelegate(typeof(Func<T, TReturnValue>), instance);
        }

        /// <summary>
        /// 调用时就像 var result = func(this, t)。
        /// </summary>
        public static Func<TInstanceType, T, TReturnValue> CreateMethod<TInstanceType>(MethodInfo method)
        {
            if (method == null)
                throw new ArgumentNullException(nameof(method));

            return (Func<TInstanceType, T, TReturnValue>)method.CreateDelegate(typeof(Func<TInstanceType, T, TReturnValue>));
        }
    }
}[/mw_shl_code]

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|php中文网 | cnphp.com ( 赣ICP备2021002321号-2 )

GMT+8, 2024-11-23 19:51 , Processed in 0.251101 second(s), 32 queries , Gzip On.

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

申明:本站所有资源皆搜集自网络,相关版权归版权持有人所有,如有侵权,请电邮(fiorkn@foxmail.com)告之,本站会尽快删除。

快速回复 返回顶部 返回列表