zoukankan      html  css  js  c++  java
  • 【C#】反射的用法及效率对比

    反射实例化类

    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

    反射调用类的方法

    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} - 直接使用反射调用");
        }
    }
    

    • 反射得到实例后调用方法和直接调用方法效率一样
    • 缓存反射方法调用和直接使用反射调用都非常耗效率

    ------------------------------------ END ------------------------------------

    欢迎扫码关注我的公众号


    码农升级
  • 相关阅读:
    微信定制开发怎么做?
    bzoj4069【APIO2015】巴厘岛的雕塑
    bzoj3174【TJOI2013】解救小矮人
    bzoj3531【SDOI2014】旅行
    单例模式
    JDK自带的定时任务
    centos6下手工编译vitess
    Rocchio算法
    Excel如何查找名字重复的数据
    MyEclipse8.5快速搭建SSH框架
  • 原文地址:https://www.cnblogs.com/gl1573/p/14411427.html
Copyright © 2011-2022 走看看