Страницы

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

воскресенье, 15 декабря 2019 г.

Существует ли возможность создавать объект определенного типа, без использования класса Activator? [дубликат]

#c_sharp


        
             
                
                    
                        
                            This question already has answers here:
                            
                        
                    
                
                        
                            Способы создания объектов в C#
                                
                                    (2 ответа)
                                
                        
                                Closed 1 год назад.
            
                    
Для приведения типов наследуемого объекта написана функция. Есть-ли какая-либо возможность
создать объект нужного типа без использования класса Activator?

public T ToObject()
{
     var o = Activator.CreateInstance(typeof(T));
     ...
     return (T)o 
}

    


Ответы

Ответ 1



Я написал простой тест для BenchmarkDotNet: [MemoryDiagnoser] public class Creator { public class A { } [Benchmark] public A ExplicitCtor() { return new A(); } [Benchmark] public A WithActivator() { return Activator.CreateInstance(); } [Benchmark] public A WithReflection() { return (A)typeof(A).GetConstructor(new Type[0]).Invoke(new object[0]); } ConstructorInfo ctor; [Benchmark] public A WithReflectionCached() { if (ctor == null) ctor = typeof(A).GetConstructor(new Type[0]); return (A)ctor.Invoke(new object[0]); } Func lambda; [Benchmark] public A WithLambla() { if (lambda == null) lambda = Expression.Lambda>(Expression.New(typeof(A)), Array.Empty()).Compile(); return lambda(); } [Benchmark] public A WithCustomActivator() { return CustomActivator.CreateInstance(); } } (CustomActivator by Sergey Teplyakov можно взять здесь) Результаты получились следующие: | Method | Mean | Error | StdDev | Median | Gen 0 | Allocated | |--------------------- |-----------:|----------:|----------:|-----------:|-------:|----------:| | ExplicitCtor | 2.591 ns | 0.0523 ns | 0.0489 ns | 2.582 ns | 0.0076 | 12 B | | WithActivator | 113.661 ns | 0.4652 ns | 0.3885 ns | 113.583 ns | 0.0074 | 12 B | | WithReflection | 369.719 ns | 6.9477 ns | 5.4243 ns | 367.856 ns | 0.0229 | 36 B | | WithReflectionCached | 281.290 ns | 0.9358 ns | 0.7814 ns | 281.415 ns | 0.0148 | 24 B | | WithLambla | 17.391 ns | 0.0700 ns | 0.0621 ns | 17.373 ns | 0.0076 | 12 B | | WithCustomActivator | 27.644 ns | 0.6665 ns | 1.3155 ns | 27.039 ns | 0.0076 | 12 B | Т.е. что мы видим: рефлексия очень медленная и даже кеширование конструктора не сильно помогает, создание объекта с помощью Activator быстрее явной рефлексии в 2,5-3 раза, но всё еще сильно медленнее явного вызова конструктора (в 40 раз!), наиболее эффективный метод, как и ожидалось — создание и кеширование делегата, создающего объекты, он всего в ~6 раз медленнее явного вызова конструктора (тут, подозреваю, медленное именно создание делегата, а сам его вызов не должен уступать явному вызову конструктора, т.е. чем больше объектов мы будем создавать, тем ближе будет средняя скорость к идеальной). Таким образом, имеет смысл переписать ваш метод во что-то вроде такого: Dictionary cache = new Dictionary(); public T Create() { if (!cache.TryGetValue(typeof(T), out var d)) d = cache[typeof(T)] = Expression.Lambda>( Expression.New(typeof(T)), Array.Empty()) .Compile(); return ((Func)d)(); }

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

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