gpt4 book ai didi

.net - 为什么 .NET IL 总是创建新的字符串对象,即使更高级别的代码引用了现有的对象?

转载 作者:行者123 更新时间:2023-12-04 22:24:26 26 4
gpt4 key购买 nike

背景:
我们有一个包含数千个伪代码函数的 XML 文档。我编写了一个实用程序来解析此文档并从中生成 C# 代码。这是生成的代码的一个大大简化的片段:

public class SomeClass
{
public string Func1() { return "Some Value"; }
public string Func2() { return "Some Other Value"; }
public string Func3() { return "Some Value"; }
public string Func4() { return "Some Other Value"; }
// ...
}

重要的一点是每个字符串值都可能由多种方法返回。我假设通过进行微小的更改,以便方法将返回对静态成员字符串的引用,这将减少程序集大小并减少程序的内存占用。例如:
public class SomeClass
{
private const string _SOME_VALUE = "Some Value";
private const string _SOME_OTHER_VALUE = "Some Other Value";
// ...

public string Func1() { return _SOME_VALUE; }
public string Func2() { return _SOME_OTHER_VALUE; }
public string Func3() { return _SOME_VALUE; }
public string Func4() { return _SOME_OTHER_VALUE; }
// ...
}

但令我惊讶的是,使用 .NET ildasm.exe 实用程序的检查表明,在这两种情况下,函数的 IL 是相同的。这是其中之一。无论哪种方式,硬编码值都会与 ldstr 一起使用:
.method public hidebysig instance string
Func1() cil managed
{
// Code size 6 (0x6)
.maxstack 8
IL_0000: ldstr "Some Value"
IL_0005: ret
} // end of method SomeClass::Func1

事实上,“优化”版本稍微差一些,因为它在程序集中包含静态字符串成员。当我使用除 之外的其他对象类型重复这个实验时字符串 ,我看到了我期望的差异。请注意,程序集是在启用优化的情况下生成的。

问题:
为什么 .NET 显然总是创建一个新的字符串对象,而不管代码是否引用了现有的对象?

最佳答案

  IL_0000:  ldstr      "Some Value"
IL_0005: ret

反汇编程序太有用了,无法向您展示真正发生的事情。从IL地址可以看出,注意ldstr指令只占用5个字节。存储该字符串的方式太少了。使用查看 + 显示 token 值来查看它的真实外观。您现在还将看到相同的字符串使用相同的标记值。这称为“实习”。

在程序被 jitt 之后, token 值仍然没有显示字符串的真正存储位置。字符串文字进入“加载器堆”,这是一个不同于垃圾收集堆的堆。它是存储静态项目的堆。或者换句话说:字符串文字经过高度优化且非常便宜。你自己不能做得更好。

关于.net - 为什么 .NET IL 总是创建新的字符串对象,即使更高级别的代码引用了现有的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6673199/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com