前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C#】反射的用法及效率对比

【C#】反射的用法及效率对比

作者头像
丹枫无迹
发布2021-02-25 16:31:53
1.2K0
发布2021-02-25 16:31:53
举报
文章被收录于专栏:学无止境

反射实例化类

代码语言:javascript
复制
public class Person
{
    public string Name { get; set; }

    public Person(string name)
    {
        this.Name = name;
    }

    public string Say(string msg)
    {
        return $"{Name}: {msg}";
    }
}

class Program
{
    // 测试次数
    const int count = 10000000;

    static void Main(string[] args)
    {
        CreateInstance0();
        CreateInstance1();
        CreateInstance2();
        CreateInstance3();
        CreateInstance4();

        Console.Read();
    }

    static void CreateInstance0()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();

        for (var i = 0; i < count; i++)
        {
            Person person = new Person("张三");
        }

        watch.Stop();
        Console.WriteLine($"{watch.Elapsed} - new");
    }

    static void CreateInstance1()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();

        for (var i = 0; i < count; i++)
        {
            object person = Activator.CreateInstance(typeof(Person), "张三");
        }

        watch.Stop();
        Console.WriteLine($"{watch.Elapsed} - Activator.CreateInstance");
    }

    static void CreateInstance2()
    {
        Assembly assembly = Assembly.GetExecutingAssembly();

        Stopwatch watch = new Stopwatch();
        watch.Start();

        for (var i = 0; i < count; i++)
        {
            Person obj = (Person)assembly.CreateInstance("ConsoleTest.Person", true, BindingFlags.Default, null, new object[] { "张三" }, null, null);
        }

        watch.Stop();
        Console.WriteLine($"{watch.Elapsed} - Assembly.CreateInstance");
    }

    static void CreateInstance3()
    {
        Assembly assembly = Assembly.GetExecutingAssembly();

        Stopwatch watch = new Stopwatch();
        watch.Start();

        for (var i = 0; i < count; i++)
        {
            Type type = assembly.GetType("ConsoleTest.Person");
            object person = Activator.CreateInstance(type, "张三");
        }
        watch.Stop();
        Console.WriteLine($"{watch.Elapsed} - Assembly.CreateInstance1");
    }

    static void CreateInstance4()
    {
        Assembly assembly = Assembly.GetExecutingAssembly();

        Stopwatch watch = new Stopwatch();
        watch.Start();

        Type type = assembly.GetType("ConsoleTest.Person");
        for (var i = 0; i < count; i++)
        {
            object person = Activator.CreateInstance(type, "张三");
        }
        watch.Stop();
        Console.WriteLine($"{watch.Elapsed} - Assembly.CreateInstance2");
    }
}
  • 通过反射实例化对象,要比直接 new 要慢 50 倍左右
  • assembly.CreateInstance 要比 Activator.CreateInstance 慢,主要的性能损耗在 Assembly.GetType

反射调用类的方法

代码语言:javascript
复制
class Program
{
    // 测试次数
    const int count = 10000000;

    static void Main(string[] args)
    {
        InvokeMethod0();
        InvokeMethod1();
        InvokeMethod2();
        InvokeMethod3();
        InvokeMethod4();

        Console.Read();
    }

    static void InvokeMethod0()
    {
        Person person = new Person("张三");

        Stopwatch watch = new Stopwatch();
        watch.Start();

        for (var i = 0; i < count; i++)
        {
            string name = person.Say("Hello World!");
        }

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

    static void InvokeMethod1()
    {
        Person person = (Person)Activator.CreateInstance(typeof(Person), "张三");

        Stopwatch watch = new Stopwatch();
        watch.Start();

        for (var i = 0; i < count; i++)
        {
            string name = person.Say("Hello World!");
        }

        watch.Stop();
        Console.WriteLine($"{watch.Elapsed} - 反射缓存类调用");
    }

    static void InvokeMethod2()
    {
        Person person = (Person)Activator.CreateInstance(typeof(Person), "张三");
        MethodInfo method = typeof(Person).GetMethod(nameof(Person.Say), new Type[] { typeof(string) });
        Func<string, string> func = (Func<string, string>)method.CreateDelegate(typeof(Func<string, string>), person);

        Stopwatch watch = new Stopwatch();
        watch.Start();

        for (var i = 0; i < count; i++)
        {
            string result = func("Hello World!");
        }

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

    static void InvokeMethod3()
    {
        Person person = (Person)Activator.CreateInstance(typeof(Person), "张三");

        MethodInfo method = typeof(Person).GetMethod(nameof(Person.Say), new Type[] { typeof(string) });

        object[] parameters = new object[] { "Hello World!" };

        Stopwatch watch = new Stopwatch();
        watch.Start();

        for (var i = 0; i < count; i++)
        {
            string name = (string)method.Invoke(person, parameters);
        }

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

    static void InvokeMethod4()
    {
        Person person = (Person)Activator.CreateInstance(typeof(Person), "张三");

        object[] parameters = new object[] { "Hello World!" };

        Stopwatch watch = new Stopwatch();
        watch.Start();

        for (var i = 0; i < count; i++)
        {
            string result = (string)(typeof(Person).GetMethod(nameof(Person.Say))?.Invoke(person, parameters));
        }

        watch.Stop();
        Console.WriteLine($"{watch.Elapsed} - 直接使用反射调用");
    }
}
  • 反射得到实例后调用方法和直接调用方法效率一样
  • 缓存反射方法调用和直接使用反射调用都非常耗效率
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-02-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 反射实例化类
  • 反射调用类的方法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档