Pull to refresh

Comments 18

Эм. А что мешало статическое поле проинициализировать делегатом конструктора? Работает в разы быстрее Reflection и не надо никаких лишних телодвижений в виде лямбд.
Вы, видимо, про первую часть. Так, по сути, это и есть решение.
Ну я пока что вижу internal SteppedPattern(Func bucketProvider) и необходимость туда явно передавать лямбду, на мой взгляд это несколько криво. К сожалению, CreateDelegate на ConstructorInfo, похоже, не натравить, так что наиболее правильным решением будет держать где-то отдельный класс, эмитящий переходники-создавалки, таким образом вместо некрасивой передачи лямбд мы получим банальное static Func ctorT = Utils.GetDefaultConstructor();
А, да… Ну тогда это по сути, комбинация обоих случаев в статье. Первое — надо создавать объекты. Второе — необходимо кэшировать делегаты создания объектов… )
советую почитать про паттерн Фабрика
Фабрики нужны там, где имеет смысл их использовать, а не повсеместно, где нужно создать экземпляр класса, переданного параметром Generic-а.
Да, действительно забавно что ограничение new() раскрывается в T t = default(T) ?? Activator.CreateInstance(); Тоже синтаксический сахар получается…
Вместо передачи функции-провайдера можно использовать кешированные Expressions:
class Operator<T>{
    static readonly Func<T> _new = 
        Expression.Lambda<Func<T>>(Expression.New(typeof(T))).Compile();
    public static Func<T> New { get { return _new; } }
}

Тогда вместо
    T t = new T();

можно писать
    T t = Operator<T>.New();

Первый вызов будет долгим, потому, что создается и кешируется Expression, но остальные практически равны прямому вызову оператора , а иногда почему-то даже быстрее.
Да, хороший выход из положения :)
Только что проверил результаты для вашего предложения. Самое интересное что для структур работает быстрее, а для объектов — медленнее:
Environment: CLR 4.0.30319.17379 on Microsoft Windows NT 6.1.7600.0
SmallStructWithConstraint: 1588ms
SmallStructWithProvider : 1704ms
SmallStructWithExpression: 1235ms
LargeStructWithConstraint: 10578ms
LargeStructWithProvider : 9495ms
LargeStructWithExpression: 4662ms
SmallClassWithConstraint : 14309ms
SmallClassWithProvider : 2543ms
SmallClassWithExpression : 3664ms
LargeClassWithConstraint : 14156ms
LargeClassWithProvider : 3317ms
LargeClassWithExpression : 4505ms
У меня похожие результаты.
Для параметризации классами все медленнее потому, что для них работает type erasure с заменой на __Canon, и в результате соотв. код часто использует словари.
Если вы хотите поручить компилятору самостоятельно создавать ваши объекты, ожидайте оверхеда. Наличие дженериков должно способствовать статической типизации и оптимальной работе с ValueType, но никак не избыточной лени :)
Не соглашусь. Когда я беру компилятор от MS, я ему доверяю. Потому как его делают годами. Его оптимизирую, точат, и делают т.о., чтобы вещи, реализуемые компилятором, работали быстро. Потому как если люди будут переделывать за компилятором, нах такой компилятор этим людям? Избыточная лень — это когда тебе дают что-то реализованное очень хорошо, а человек срет, дескать, оно само не программируется, не автонастраивается, и т.д., и т.п… А когда дают базовую конструкцию языка, которая работает через жопу рефлексию, т.е. откровенно на халяву… Вот это стоит поругать.
Оптимизация да, это хорошо. Но решение в данном случае очевидное. Как же еще создавать неизвестный объект, как не через активатор/рефлекс? Поясню. Ваша сборка с дженериком совершенно не имеет понятия какой тип будет использован в используемом приложении. Всё логично. Хотите скорости, управляйте потоками сами. В большинстве случаев этого не требуется. Спасибо компилятору.
наверное, мне одному кажется что пример из статьи так и должен был работать. если бы компилятор генерировал для конструктора лямбду или делегат без моего ведома, что есть просто хак, то именно это стоит поругать.
небезызвестный Липперт отвечая на вопрос почему это или то не реализовано в C#, отвечает так: «C# — это прагматичный язык».
Нет, это должно было быть сделано отдельной IL командой. А ее реализация — оптимизирована.
такой функционал на уровне CLR будет наиболее правильным. вот async из C# 5 с его State Machine мне кажется правильным подходом, именно этого и стоит ожидать в кодогенерации, а не то решение из статьи.
Sign up to leave a comment.