Страницы

Поиск по вопросам

среда, 10 октября 2018 г.

Способы создания объектов в C#

Я знаю 1 способ создать объекта в C#:
public static class ObjectCreator { public static T GetObject() where T : class { return (T)Activator.CreateInstance(typeof(T)); } }
Есть ли более производительные?
Update класс с известными способами:
public class ObjectCreator where T: new() { protected Func V4Lambda;
protected Func V5Lambda;
public ObjectCreator() { Type sType = typeof(T);
//V4 V4Lambda = Expression.Lambda>(Expression.New(sType)).Compile();
//V5 V5Lambda = DynamicModuleLambdaCompiler.GenerateFactory(); }
public T V1() { return (T)Activator.CreateInstance(typeof(T)); }
public T V2() { return new T(); }
public T V3() { return CustomActivator.CreateInstance(); }
public T V4() { return V4Lambda(); }
public T V5() { return V5Lambda(); } }
public static class CustomActivator { public static T CreateInstance() where T : new() { return ActivatorImpl.Factory(); }
private class ActivatorImpl where T : new() { private static readonly Expression> _expr = () => new T();
public static readonly Func Factory = _expr.Compile(); } }
public static class DynamicModuleLambdaCompiler { public static Func GenerateFactory() where T : new() { Expression> 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)method.CreateDelegate(typeof(Func)); } }
Результаты моего тестирования:


Ответ

В следующих статьях Сергея Теплякова
Исследуем new() ограничение в C# Dissecting the new() constraint in C#: a perfect example of a leaky abstraction
делается вывод, что самый быстрый способ создания объекта - это распарсить лямбду в выражение и скомпилировать его:
public static class DynamicModuleLambdaCompiler { public static Func GenerateFactory() where T:new() { Expression> 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)method.CreateDelegate(typeof(Func)); } }

public static class FastActivator where T : new() { ///

/// Extremely fast generic factory method that returns an instance /// of the type . /// public static readonly Func Create = DynamicModuleLambdaCompiler.GenerateFactory(); }

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 |

Комментариев нет:

Отправить комментарий