C#编译器如何在文件类中生成这么长的ID?

问题描述 投票:0回答:1

给定以下 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...
是文件类的名称。

我不明白的是这很长,看似两者之间的ID:

FFEAE62924BA736A3C9E8DE39EA3099D227B65B02C0A6BC7FECCB5FF0D5B9D8B3

据我了解,它似乎根据源文件名而有所不同,当两个尖括号之间的文本

<Class1>
似乎已经发挥作用时,这是令人惊讶的。

C#编译器如何产生这个ID?我在互联网上找不到任何相关信息。

c# .net decompiling c#-11.0
1个回答
0
投票

我决定进一步挖掘 Roslyn 的源代码。使用临时自动化工具查找每个包含

FileLocalType
的 C# 源文件,大约有 12 个 C# 源文件。

终于,我来到了这里。生成此ID的代码:

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();
        }

定义于here

进一步查看后,这才是真正的ID。 这里的神秘ID是定义文件类的源文件的名称,使用SHA256哈希算法加密。这确实不容易找到。是的,我确实需要这个算法,而不是仅仅生成一个随机整数,然后对结果进行字符串化,这将是执行此操作的传统方法,但是,这回答了问题。

© www.soinside.com 2019 - 2024. All rights reserved.