RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 715920
Accepted
Kunoichi
Kunoichi
Asked:2020-09-08 17:50:33 +0000 UTC2020-09-08 17:50:33 +0000 UTC 2020-09-08 17:50:33 +0000 UTC

在 C# 中创建对象的方法

  • 772

我知道在 C# 中创建对象的一种方法:

public static class ObjectCreator
{
    public static T GetObject<T>() where T : class
    {
        return (T)Activator.CreateInstance(typeof(T));
    }
}

有没有更高产的?

用已知方式更新类:

 public class ObjectCreator<T> where T: new()
{
    protected Func<T> V4Lambda;

    protected Func<T> V5Lambda;

    public ObjectCreator()
    {
        Type sType = typeof(T);

        //V4
        V4Lambda = Expression.Lambda<Func<T>>(Expression.New(sType)).Compile();

        //V5
        V5Lambda = DynamicModuleLambdaCompiler.GenerateFactory<T>();
    }

    public T V1()
    {
        return (T)Activator.CreateInstance(typeof(T));
    }

    public T V2()
    {
        return new T();
    }

    public T V3()
    {
        return CustomActivator.CreateInstance<T>();
    }

    public T V4()
    {
        return V4Lambda();
    }

    public T V5()
    {
        return V5Lambda();
    }
}

public static class CustomActivator
{
    public static T CreateInstance<T>() where T : new()
    {
        return ActivatorImpl<T>.Factory();
    }

    private class ActivatorImpl<T> where T : new()
    {
        private static readonly Expression<Func<T>> _expr = () => new T();

        public static readonly Func<T> Factory = _expr.Compile();
    }
}

public static class DynamicModuleLambdaCompiler
{
    public static Func<T> GenerateFactory<T>() where T : new()
    {
        Expression<Func<T>> expr = () => new T();
        NewExpression newExpr = (NewExpression)expr.Body;

        var method = new DynamicMethod(
            name: "lambda",
            returnType: newExpr.Type,
            parameterTypes: new Type[0],
            m: typeof(DynamicModuleLambdaCompiler).Module,
            skipVisibility: true);

        ILGenerator ilGen = method.GetILGenerator();
        // Constructor for value types could be null
        if (newExpr.Constructor != null)
        {
            ilGen.Emit(OpCodes.Newobj, newExpr.Constructor);
        }
        else
        {
            LocalBuilder temp = ilGen.DeclareLocal(newExpr.Type);
            ilGen.Emit(OpCodes.Ldloca, temp);
            ilGen.Emit(OpCodes.Initobj, newExpr.Type);
            ilGen.Emit(OpCodes.Ldloc, temp);
        }

        ilGen.Emit(OpCodes.Ret);

        return (Func<T>)method.CreateDelegate(typeof(Func<T>));
    }
}

我的测试结果:

在此处输入图像描述

c#
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Qwertiy
    2020-09-08T20:06:01Z2020-09-08T20:06:01Z

    在 Sergei Teplyakov 的以下文章中

    • 探索 C# 中的 new() 约束
    • 剖析 C# 中的 new() 约束:泄漏抽象的完美示例

    它得出的结论是,创建对象的最快方法是将 lambda 解析为表达式并编译它:

    public static class DynamicModuleLambdaCompiler
    {
        public static Func<T> GenerateFactory<T>() where T:new()
        {
            Expression<Func<T>> expr = () => new T();
            NewExpression newExpr = (NewExpression)expr.Body;
    
            var method = new DynamicMethod(
                name: "lambda", 
                returnType: newExpr.Type,
                parameterTypes: new Type[0],
                m: typeof(DynamicModuleLambdaCompiler).Module,
                skipVisibility: true);
    
            ILGenerator ilGen = method.GetILGenerator();
            // Constructor for value types could be null
            if (newExpr.Constructor != null)
            {
                ilGen.Emit(OpCodes.Newobj, newExpr.Constructor);
            }
            else
            {
                LocalBuilder temp = ilGen.DeclareLocal(newExpr.Type);
                ilGen.Emit(OpCodes.Ldloca, temp);
                ilGen.Emit(OpCodes.Initobj, newExpr.Type);
                ilGen.Emit(OpCodes.Ldloc, temp);
            }
    
            ilGen.Emit(OpCodes.Ret);
    
            return (Func<T>)method.CreateDelegate(typeof(Func<T>));
        }
    }
    
    public static class FastActivator<T> where T : new()
    {
        /// <summary>
        /// Extremely fast generic factory method that returns an instance
        /// of the type <typeparam name="T"/>.
        /// </summary>
        public static readonly Func<T> Create =
            DynamicModuleLambdaCompiler.GenerateFactory<T>();
    }
    
                      Method |       Mean |    StdDev |  Gen 0 |
    ------------------------ |----------- |---------- |------- |
     ActivatorCreateInstance | 95.0161 ns | 1.0861 ns | 0.0005 |
            FuncBasedFactory |  6.5741 ns | 0.0608 ns | 0.0034 |
      FastActivator_T_Create |  5.1715 ns | 0.0466 ns | 0.0034 |
    
    • 9
  2. VladD
    2020-09-08T22:33:37Z2020-09-08T22:33:37Z

    您几乎不应该进行低级微优化。(因为编译器迟早会优化得更好。)

    但是如果在某些地方你真的需要优化,那么只需将创建函数传递到Func<T>你需要的地方就足够了,就是这样:

    public class ObjectCreator<Т>
    {
        Func<T> create;
        public ObjectCreator(Func<T> create) => this.create = create;
        public T GetObject() => create();
    }
    

    你会失去一些抽象,但你应该去,而不是跳棋?这是最快的方法。

    在正确的地方调用正确的构造函数会更快。因为调用代表不是免费的。另一方面,如果您需要纳米优化,那么您选择了错误的平台。

    基准:

    BenchmarkDotNet=v0.10.9, OS=Windows 7 SP1 (6.1.7601)
    Processor=Intel Core i7-2600K CPU 3.40GHz (Sandy Bridge), ProcessorCount=8
    Frequency=3320429 Hz, Resolution=301.1659 ns, Timer=TSC
      [Host]     : .NET Framework 4.7 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.2053.0
      DefaultJob : .NET Framework 4.7 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.2053.0
    
    
                                             Method |      Mean |     Error |    StdDev |
    ----------------------------------------------- |----------:|----------:|----------:|
                        V1_Activator_CreateInstance | 70.639 ns | 0.3354 ns | 0.3138 ns |
                            V2_NewGenericConstraint | 77.813 ns | 0.2788 ns | 0.2608 ns |
                  V3_CustomActivator_CreateInstance | 20.237 ns | 0.0562 ns | 0.0498 ns |
                              V4_Expression_Compile | 11.175 ns | 0.1693 ns | 0.1584 ns |
     V5_DynamicModuleLambdaCompiler_GenerateFactory |  4.822 ns | 0.0322 ns | 0.0301 ns |
                                    V6_Factory_Func |  3.967 ns | 0.0247 ns | 0.0231 ns |
                         V7_Direct_Constructor_Call |  3.047 ns | 0.0207 ns | 0.0194 ns |
    
    • 6

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5