.NET C# 三种实例化一个类的方式的性能比较

本文内容

  • 实例化一个类的方式
  • 用 New 关键字实例化一个类
  • 用 Activator 实例化一个类
  • 用 Assembly 实例化一个类
  • 性能比较
  • 环境
  • 比较
  • 分析
  • 代码

在开发应用程序时,能够动态实例化一个类很有用。给出类的一个字符串名称,就能够创建这个类的一个实例。若这些需要实例化的类都继承同一个接口(如本例的 IPerson),那么实例化的 object 类型转换后可以赋值给这个接口。这很方便。否则,就得用 swtich-case 语句(估计会很长)。

那么,接下来的问题,实例化一个类的性能如何。

之前,我用 Assembly 较多,写本文后,发觉好像不妥。

实例化一个类的方式


  • 用 New 关键字实例化一个类

New 关键字用于创建对象和调用构造函数。是实例化一个类最常见的方式。

  • 用 Activator 实例化一个类

Activator 用以在本地或从远程创建对象类型,或获取对现有远程对象的引用。其 CreateInstance 方法创建在程序集中定义的类型的实例。

  • 用 Assembly 实例化一个类

Assembly 表示一个程序集,它是一个可重用、无版本冲突并且可自我描述的公共语言运行库应用程序构造块。该类可以加载程序集、浏览程序集的元数据和构成部分、发现程序集中包含的类型以及创建这些类型的实例。

加载程序集的推荐方式是使用 Load 方法。GetType 方法可用于在程序集中搜索特定类型。CreateInstance 方法可用于在程序集中搜索和创建类型的实例。

本文通过这三种方式来创建一个类的实例。

性能比较

环境

  • VS 2008 .NET Framework 3.5
  • Intel CPU Duo  T5450 1.66GHz
  • Memory 2G
比较


假设,Demo 中使用的类都在同一个程序集。

using System;
 
namespace InstancePerformance
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("实例化一个类的性能比较(单位:毫秒)");
            Console.Write("                    ");
            for (int i = 1; i <= 10; i++)
                Console.Write("{0:G}", i.ToString().PadLeft(5));
            Console.Write("\n");
            // New Key
            Console.Write("InstanceByNew".PadRight(20));
            for (int i = 1; i <= 10; i++)
                InstanceByNewKey.Create();
            Console.Write("\n");
            // Activator
            Console.Write("InstanceByActivator".PadRight(20));
            for (int i = 1; i <= 10; i++)
                InstanceByActivator.Create();
            Console.Write("\n");
            // Assembly
            Console.Write("InstanceByAssembly".PadRight(20));
            for (int i = 1; i <= 10; i++)
                InstanceByAssembly.Create();
            Console.Write("\n");
 
            Console.ReadKey();
        }
    }
}

其中,

  • InstanceByNewKey.Create() 用 New 关键字实例化一个类;
  • InstanceByActivator.Create() 用 Activator 实例化一个类;
  • InstanceByAssembly.Create() 用 Assembly 实例化一个类。

在“代码”小节是这三个方法的实现代码。

  • 为了便于测试,时间不至于小得可怜,以上每个方法实例化十万次,也就是创建十万个对象。
  • 为了便于比较,对以上每个方法都调用 10 次。进行横向和纵向比较。

分析


由上图可以看出,用 Activator 实例化一个类最快;其次是用 New 关键字;最慢的是用 Assembly 实例化。Activator 比 用 New 都快。

因此,若想动态实例化一个类,根据你的实际情况,尽量将需要实例化的类放在同一个程序集。

代码


代码段 1:IPerson 接口和 Person 类

public class IPerson
{
 
}
public class Person : IPerson

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

代码段 2:使用 New 关键字实例化

public class InstanceByNewKey
{
    /// <summary>
    /// 直接调用
    /// </summary>
    public static void Create()
    {
        IPerson person = null;
        Stopwatch watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < 100000; i++)
            person = new Person("My" + i);
        watch.Stop();
        Console.Write(watch.ElapsedMilliseconds.ToString().PadLeft(5));
    }
}

另外,若该代码段写成如下,是没有必要的。其他代码段类似。

Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 100000; i++)
    IPerson person = new Person("My" + i);
watch.Stop();
Console.Write(watch.ElapsedMilliseconds.ToString().PadLeft(5));

代码段 3:使用 Activator 实例化

public class InstanceByActivator
{
    /// <summary>
    /// 实例化反射
    /// </summary>
    public static void Create()
    {
        Type type = Type.GetType("InstancePerformance.Person");
        IPerson person = null;
 
        Stopwatch watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < 100000; i++)
        {
            object obj = Activator.CreateInstance(type);
            person = obj as IPerson;
        }
        watch.Stop();
        Console.Write(watch.ElapsedMilliseconds.ToString().PadLeft(5));
    }
}

代码段 4:使用 Assembly 实例化

public class InstanceByNewKey
{
    /// <summary>
    /// 直接调用
    /// </summary>
    public static void Create()
    {
        IPerson person = null;
        Stopwatch watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < 100000; i++)
            person = new Person("My" + i);
        watch.Stop();
        Console.Write(watch.ElapsedMilliseconds.ToString().PadLeft(5));
    }
}

下载 Demo

时间: 2024-12-31 21:44:12

.NET C# 三种实例化一个类的方式的性能比较的相关文章

三种方式实例化一个类的性能情况

源内容:http://www.cnblogs.com/shouce/p/5558095.html#undefined 下面的内容是根据“源内容”进行了整改.补充. 三种方式实例化一类,包括无参数构造形式与有参数构造形式性能测试. 使用new关键字创建类实例(常用方式). 使用Activator激活器类创建类实例(Activator用以在本地或从远程创建对象类型,或获取对现有远程对象的引用). 使用Assembly程序集创建类实例(Assembly表示一个程序集,它是一个可重用.无版本冲突并且可自

spring三种实例化bean的方式

1构造函数实例化 2静态工厂方法实例化 3实例工厂方法实例化 service接口: package service; public interface PersonService { public void save(); } PersonServiceBean: package service.impl; import service.PersonService; public class PersonServiceBean implements PersonService { public

latex三种标准文类book, report, article的章节命令与层次深度

Latex有三种标准文类:book, report, article. 每种文类的章节命令和层次深度如下: 三种标准文类的章节命令与层次深度 层次深度 层次名 book report article -1 part \part \part   0 chapter \chapter \chapter \part 1 section \section \section \section 2 subsection \subsection \subsection \subsection 3 subsub

ASP.NET MVC 主要的四种过滤器和三种具体实现类

原文:ASP.NET MVC 主要的四种过滤器和三种具体实现类 4种常用过滤器(IAuthrorizationFilter.IActionFilter.IResultFilter.IExceptionFilter) 和 3种具体实现类(AuthorizeAttribute.ActionFilterAttribute(Action + Result).HandleErrorAttribute) (图片可放大) 原文地址:https://www.cnblogs.com/lonelyxmas/p/10

Android中三种超实用的滑屏方式汇总(转载)

Android中三种超实用的滑屏方式汇总 现如今主流的Android应用中,都少不了左右滑动滚屏这项功能,(貌似现在好多人使用智能机都习惯性的有事没事的左右滑屏,也不知道在干什么...嘿嘿),由于前段时间项目的需要,所以也对其研究了一下,总的来说滑屏实现有三种方式:(至于其他的实现方式目前后还没碰到...) 1.ViewPager 2.ViewFlipper 3.ViewFlow 一.ViewPager 官方文档介绍:http://developer.android.com/reference/

[精通Objective-C]三种实现并发编程的方式

[精通Objective-C]三种实现并发编程的方式 参考书籍:<精通Objective-C>[美] Keith Lee 目录 精通Objective-C三种实现并发编程的方式 目录 线程 隐式创建并启动线程 显示创建并启动线程 操作和操作队列 用操作类实现并发 用操作队列实现并发 分派队列GCD 三种方式的比较 线程 隐式创建并启动线程 使用NSObject类中的performSelectorInBackground: withObject:方法可以隐式地创建和启动用于执行对象中方法的新线程

Object-C的类可以多重继承吗?可以实现多个接口吗?category是什么?重写一个类的方式用继承好还是分类好,为什么?

答:Object-c的类不可以多重继承,可以实现多个接口(协议),Category是类别,重写一个类的方式一般用分类更好,仅仅对分类有效,不会影响到其他类与原有类的关系.category的主要作用是为已经存在的类添加方法.除此之外,apple官方还推荐了另外两种使用场景: 1.可以把类的实现分开在几个不同的文件,这样做有几个显而易见的好处:第一,可以减少单个文件的体积.第二,可以不同功能的组织放到不同的category中去.第三,可以由多个不同的开发者来共同完成一个类.第三,可以按需要来加载不同

Js之Dom学习-三种获取页面元素的方式、事件、innerText和innerHTML的异同

一.三种获取页面元素的方式: getElementById:通过id来获取 <body> <input type="text" value="请输入一个值:" id="txt"/> <input type="button" value="按钮" id="btn"/> <script> var txt=document.getElementB

三种呈现错误页面的方式

三种呈现错误页面的方式 由于ASP.NET Core应用是一个同时处理多个请求的服务器应用,所以在处理某个请求过程中抛出的异常并不会导致整个应用的终止.出于安全方面的考量,为了避免敏感信息的外泄,客户端在默认的情况下并不会得到详细的出错信息,这无疑会在开发环境下增加查错纠错的难度.对于生产环境来说,我们也希望最终用户能够根据具体的错误类型得到具有针对性并且友好的错误消息.ASP.NET Core提供了相应的中间件帮助我们将定制化的错误信息呈现出来,这些中间件都定义在"Microsoft.AspN