Подтвердить что ты не робот

Предоставляет ли кеширование возвращаемое значение typeof (MyControl) любую оптимизацию?

Я вижу код, похожий на следующий, покрашенный о некоторых собственных элементах управления WPF:

static MyControl {
    Type typeFromHandle = typeof(MyControl);

    // Which is used in various places
    SomeProperty.OverrideMetadata(typeFromHandle, ...);
    CommandManager.RegisterClassInputBinding(typeFromHandle, ...);
    EventManager.RegisterClassHandler(typeFromHandle, ...);
}

Похоже, что следующий код будет иметь одинаковую производительность:

static MyControl {
    SomeProperty.OverrideMetadata(typeof(MyControl), ...);
    CommandManager.RegisterClassInputBinding(typeof(MyControl), ...);
    EventManager.RegisterClassHandler(typeof(MyControl), ...);
}

Поддерживает ли этот подход какую-либо выгоду при использовании JIT-кода или во время выполнения?

4b9b3361

Ответ 1

Кэширование typeof даст вам небольшой прирост производительности. На следующей странице приведены следующие этапы:

Typeof expression used: 2.55 ns
Type object cached:     0.64 ns

Если вы typeof много, или заботитесь о наносекундах, тогда это может иметь значение для вас!

Ответ 2

Короткий ответ

Да, это более оптимально, но нет, вы не должны его использовать, так как почти во всех случаях это преждевременная оптимизация. Во всяком случае, используйте его как способ обеспечения удобочитаемости кода, если вы используете typeof(MyControl) много раз.

Длинный ответ

Если вы посмотрите на IL, созданный в инструкции typeof(MyControl) в С#, вы увидите следующее:

IL_0001: ldtoken [mscorlib]MyControl
IL_0006: call class [mscorlib]System.Type
        [mscorlib]System.Type::GetTypeFromHandle(
            valuetype [mscorlib]System.RuntimeTypeHandle)

Эти инструкции выполняют следующие действия:

  • Загружает RuntimeTypeHandle (инструкция ldtoken IL) в стек (концепция CLR, а не С#/.NET одного).
  • Получите Type из RuntimeTypeHandle (вызов Type.GetTypeFromHandle).

Сравните это с назначением типа переменной типа с сохраненным в экземпляре:

IL_0014: ldloc.2

Обратите внимание: расположение (1, 2 и т.д.) будет меняться в зависимости от других переменных, но в конечном итоге это загрузка ссылочного типа.

Сравнение двух, вызов уже назначенной переменной всегда будет быстрее. Первый должен загрузить дескриптор типа, а затем он должен вызвать метод, чтобы разрешить дескриптор в Type; второй метод - это просто ссылка на локальную переменную.

Однако, как и большинство других сообщений, это наиболее определенно можно рассматривать как случай преждевременной оптимизации, поэтому я бы предложил не делать этого, если вы считаете, что ваш код неэффективен.

Можно утверждать, что лучше с точки зрения повторного использования кода, как если бы вам пришлось менять тип, вы бы изменили его в меньшем количестве мест; вы не будете погружены в море заявлений typeof.

Наконец, что касается WPF, это то, что они должны были сделать, учитывая требования к производительности (как и любая система UI); WPF обладает огромным количеством управляемых объектов, гораздо больше по сравнению с Windows Forms и должен учитывать производительность этих объектов, чтобы он мог визуализировать пользовательский интерфейс как можно быстрее.

В результате вы увидите что-то вроде этого:

private static readonly object TrueObject = true;
private static readonly object FalseObject = false;

// Later on.
DoSomething(condition ? TrueObject : FalseObject);

// Where
void DoSomething(object value)
{
    // Compare to true/false objects.
    if (value == TrueObject)
    {
        // True case.
    }
    else if (value == FalseObject)
    {
        // False case.
    }
    else
    {
        // Invalid.
        throw new InvalidOperationException();
    }
}

Причина этого проста; большая часть WPF предоставляет свойства/методы с объектами в качестве параметров вместо строго типизированных значений. Когда задействуются типы значений, это может привести к огромному количеству бокса/распаковки.

Чтобы обойти это, у них есть один экземпляр, который помещен в коробку/распакован, когда они точно знают, какие значения будут вставляться в коробку/распаковывать; с a bool, это легко, существует только true и false.

Опять же, я бы не стал рекомендовать этот подход практически для любой системы, но для некоторых систем это имеет смысл.

В вашем случае я бы просто присвоил тип переменной, только для удобства чтения, а не для производительности. Если у вас есть проблемы с производительностью, сначала посмотрите на общий процесс, выделите с помощью измерений и затем оттуда.

Ответ 3

Вряд ли вы напишете код, где производительность типаof значительна, поэтому вы должны выбрать стиль кода, который наиболее понятен и обслуживаем.