Как компилятор C# создает этот длинный «идентификатор» в локальных типах файлов?

Учитывая следующие 3 класса файлов:

file class MyClass
{
}

file class MyClass2
{
}

file class MyClass3
{
    public int MyMember { get; init; }
}

После декомпиляции этого кода C# классы файлов теперь выглядят так:

internal class <Class1>FFEAE62924BA736A3C9E8DE39EA3099D227B65B02C0A6BC7FECCB5FF0D5B9D8B3__MyClass
{
}

internal class <Class1>FFEAE62924BA736A3C9E8DE39EA3099D227B65B02C0A6BC7FECCB5FF0D5B9D8B3__MyClass2
{
}

internal class <Class1>FFEAE62924BA736A3C9E8DE39EA3099D227B65B02C0A6BC7FECCB5FF0D5B9D8B3__MyClass3
{
    public int MyMember { get; init; }
}

Я понимаю, что <Class1> — это имя исходного файла, в котором был определен класс файла, а MyClass... — это имя класса файла.

Чего я не понимаю, так это очень длинного, казалось бы, идентификатора между ними:

FFEAE62924BA736A3C9E8DE39EA3099D227B65B02C0A6BC7FECCB5FF0D5B9D8B3

Насколько я понимаю, оно варьируется в зависимости от имени исходного файла, что удивительно, когда текст между двумя угловыми скобками <Class1>, кажется, уже играет роль.

Как компилятор C# создает этот идентификатор? Я не смог найти никакой информации об этом в Интернете. Кажется, без документов.

Наличие угловых скобок в имени класса делает имя класса незаконным в C# (но все же допустимым в CLR). Это делает возможным конфликт имен с другими именами в вашем коде (помните, что это делает компилятор — он может нарушить все правила, которые захочет). Генерация GUID или случайного числа с большим количеством энтропии (и преобразование результата в строку) — традиционный способ получить уникальное имя. Имя для вас не имеет значения, и вам не следует полагаться на такое поведение; беспокойтесь о задокументированном поведении

Flydog57 25.05.2024 20:49

@ Flydog57 Flydog57 Сначала я бы согласился, хотя этот вопрос задан не только из любопытства, но и потому, что он действительно нужен мне для моего проекта, и что наличие одного и того же точного идентификатора было бы полезно вместо традиционного способа генерации случайного числа или нить. В конце концов, я узнал, как генерируется этот идентификатор, несколько минут назад.

winscripter 25.05.2024 22:07
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
166
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я решил покопаться дальше в исходном коде Roslyn. С помощью временного автоматизированного инструмента для поиска каждого исходного файла C#, содержащего FileLocalType, оказалось около 12 исходных файлов C#.

В конце концов я приехал сюда. Код, который генерирует этот идентификатор:

internal static string MakeFileTypeMetadataNamePrefix(string filePath, ImmutableArray<byte> checksumOpt)
{
    var pooledBuilder = PooledStringBuilder.GetInstance();
    var sb = pooledBuilder.Builder;
    sb.Append('<');
    AppendFileName(filePath, sb);
    sb.Append('>');
    sb.Append((char)GeneratedNameKind.FileType);
    if (checksumOpt.IsDefault)
    {
        // Note: this is an error condition.
        // This is only included for clarity for users inspecting the value of 'MetadataName'.
        sb.Append("<no checksum>");
    }
    else
    {
        foreach (var b in checksumOpt)
        {
            sb.AppendFormat("{0:X2}", b);
        }
    }
    sb.Append("__");
    return pooledBuilder.ToStringAndFree();
}

Определение

Посмотрев дальше, я могу сделать вывод, что загадочный идентификатор здесь — это полный (абсолютный) путь к исходному файлу, в котором определен класс файла, хешированный с использованием алгоритма хеширования SHA256 (иногда, очевидно, SHA1, но по умолчанию SHA256). И да, мне действительно нужен этот алгоритм вместо того, чтобы просто генерировать случайное целое число и затем преобразовывать результат в строку, что было бы традиционным способом сделать это, но это отвечает на вопрос.

И по какой-то причине к этим идентификаторам добавляется буква «F» из-за этой строки кода в том же методе MakeFileTypeMetadataNamePrefix:

sb.Append('>');
/*HERE -->*/sb.Append((char)GeneratedNameKind.FileType);
if (checksumOpt.IsDefault)

В моем случае вот эта длинная хешированная строка:

FFEAE62924BA736A3C9E8DE39EA3099D227B65B02C0A6BC7FECCB5FF0D5B9D8B3

является результатом хеширования этой строки с использованием алгоритма SHA256, к результату которого добавляется буква «F»:

C:\Users\User\source\repos\TemporaryAppRepository\FileClassTest\Class1.cs

придирка: он не «зашифрован», он хэширован.

Pac0 25.05.2024 22:07

Предупреждаем: не полагайтесь на недокументированное поведение. Microsoft может изменить его в любое время.

Flydog57 26.05.2024 00:45

Другие вопросы по теме