1. 程式人生 > >【C#】反射的用法及效率對比

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

### 反射例項化類 ```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"); } } ``` ![](https://img2020.cnblogs.com/blog/753333/202102/753333-20210218131133034-337204526.png) - 通過反射例項化物件,要比直接 new 要慢 50 倍左右 - `assembly.CreateInstance` 要比 `Activator.CreateInstance` 慢,主要的效能損耗在 `Assembly.GetType` ### 反射呼叫類的方法 ```c# 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 func = (Func)method.CreateDelegate(typeof(Func), 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} - 直接使用反射呼叫"); } } ``` ![](https://img2020.cnblogs.com/blog/753333/202102/753333-20210218131103582-1881963762.png) - 反射得到例項後呼叫方法和直接呼叫方法效率一樣 - 快取反射方法呼叫和直接使用反射呼叫都非常耗效率