c# 反射用法及效率对比

本文通过实例对比了C#中直接new对象、Activator.CreateInstance和Assembly.CreateInstance等方法的性能,展示了反射在实例化对象时的效率损耗。同时,分析了反射调用方法的不同方式,包括直接调用、缓存委托调用和反射调用,指出在大量调用情况下,反射的效率问题。文章强调了在考虑性能时,反射的适当使用和优化至关重要。
摘要由CSDN通过智能技术生成

反射实例化类

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

在这里插入图片描述

反射得到实例后c#教程调用方法和直接调用方法效率一样
缓存反射方法调用和直接使用反射调用都非常耗效率
以上就是c# 反射用法及效率对比的详细内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值