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

Почему компилятор С# создает PrivateImplementationDetails из этого кода?

Я обнаружил, что следующий код:

public static class MimeHelper
    {
        public static string GetMimeType(string strFileName)
        {
            string retval;
            switch (System.IO.Path.GetExtension(strFileName).ToLower())
            {
                case ".3dm": retval = "x-world/x-3dmf"; break;
                case ".3dmf": retval = "x-world/x-3dmf"; break;
                case ".a": retval = "application/octet-stream"; break;
                // etc...
                default: retval = "application/octet-stream"; break;
            }
            return retval;
        } 
    }

заставляет компилятор создавать этот namespaceless, внутренний класс (скопирован из Reflector):

<PrivateImplementationDetails>{621DEE27-4B15-4773-9203-D6658527CF2B}
    - $$method0x60000b0-1 : Dictionary<String, Int32>
    - Used By: MimeHelper.GetMimeType(String) : String

Почему? Как я могу изменить вышеуказанный код, чтобы этого не произошло (просто из интереса)

Спасибо

Эндрю

4b9b3361

Ответ 1

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

ASIDE. Я предположил, что словарь сохранил карту из каждого случая в индекс на другую карту для возвращаемых значений. Согласно @Scott (см. Комментарии), он фактически хранит индекс для метки для кода, который должен быть выполнен для этого случая. Это имеет смысл, если учесть, что код, который будет выполняться для каждого случая, может отличаться и может быть намного длиннее, чем в данном примере.

РЕДАКТИРОВАТЬ. Основываясь на вашем комментарии, я думаю, что у меня может возникнуть соблазн сохранить сопоставления во внешнем файле конфигурации, прочитать их во время запуска и построить фактическую карту - либо одну карту уровня от ключа к значению или подобную многоуровневую карту от ключа к индексу и индекса к значению. Я думаю, было бы легче поддерживать эти сопоставления в файле конфигурации, чем обновлять код каждый раз, когда вам нужно было добавлять или удалять конкретный случай.

Ответ 2

Что происходит, компилятор создает внутренний класс, который он испускает во время компиляции. Этот класс называется <PrivateImplementationDetails>{99999999-9999-9999-9999-999999999999}, компонент GUID этого класса генерируется во время компиляции, поэтому он изменяется с каждой сборкой. Внутри этого класса есть словарь, который содержит разные переменные case, и int, соответствующее каждому значению. Затем он заменяет оператор switch поиском в словаре, чтобы получить соответствующий int, и делает переключатель на значение int (гораздо более эффективное, чем сравнение с кучей скрингов).

Ответ 3

См. это, например.