c# 反射用法及效率对比

 更新时间:2021年02月19日 11:52:17   作者:丹枫无迹  
这篇文章主要介绍了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");
  }
}

  • 通过反射实例化对象,要比直接 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# 反射的资料请关注脚本之家其它相关文章!

相关文章

  • C#修改IIS站点framework版本号的方法

    C#修改IIS站点framework版本号的方法

    这篇文章主要介绍了C#修改IIS站点framework版本号的方法,涉及C#调用使用ASP.NET IIS注册工具Aspnet_regiis.exe进行IIS站点framework版本号修改的方法,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • C#编程获取资源文件中图片的方法

    C#编程获取资源文件中图片的方法

    这篇文章主要介绍了C#编程获取资源文件中图片的方法,涉及C#针对项目中资源文件操作的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08
  • C#版Tesseract库的使用技巧

    C#版Tesseract库的使用技巧

    本文给大家分享C#版Tesseract库的使用技巧,在这里大家需要注意一下tesseract的识别语言包要自己下载后包含到项目里面,并设置为始终复制,或者直接把这个文件包放到运行程序目录(bin\debug)下的,具体实现代码跟随小编一起学习下吧
    2021-05-05
  • C#之HttpClient设置cookies的两种方式

    C#之HttpClient设置cookies的两种方式

    这篇文章主要介绍了C#之HttpClient设置cookies的两种方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • c#使用S22.Imap收剑灵激活码邮件代码示例(imap收邮件)

    c#使用S22.Imap收剑灵激活码邮件代码示例(imap收邮件)

    一个IMAP收发邮件的类库S22.IMAP,方便易用,下面来个例子可以收剑灵激活码邮件
    2013-12-12
  • C#读写Config配置文件案例

    C#读写Config配置文件案例

    这篇文章介绍了C#读写Config配置文件的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • C#给PDF文件添加水印

    C#给PDF文件添加水印

    这篇文章主要为大家详细介绍了C#给PDF文件添加水印的相关代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • c# winform异步不卡界面的实现方法

    c# winform异步不卡界面的实现方法

    这篇文章主要给大家介绍了关于c# winform异步不卡界面的实现方法,文中通过示例代码介绍的非常详细,对大家学习或者使用c#具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-07-07
  • c# 获取照片的经纬度和时间的示例代码

    c# 获取照片的经纬度和时间的示例代码

    这篇文章主要介绍了c# 获取照片的经纬度和时间的示例代码,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2020-11-11
  • C# 下载文件 删除文件 写入文本的实例

    C# 下载文件 删除文件 写入文本的实例

    下面小编就为大家分享一篇C# 下载文件 删除文件 写入文本的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12

最新评论