我今天正在执行一些重构,我注意到一件我无法理解的奇怪事情......或者更好的是,我部分同意我在网上找到的内容,但仍有一些问题。
请考虑这个简单的例子
class Program
{
public static readonly string a = "a";
public const string b = "b";
static void Main(string[] args)
{
Console.WriteLine(a);
Console.WriteLine(b);
}
}
现在,如果我查看生成的 IL 代码(通过来自 resharp 的 IL 浏览器获得)
我看到以下代码
.method private hidebysig static void
Main(
string[] args
) cil managed
{
.entrypoint
.maxstack 8
// [16 13 - 16 34]
IL_0000: ldsfld string ConsoleApp4.Program::a
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
// [18 13 - 18 34]
IL_000a: ldstr "b"
IL_000f: call void [mscorlib]System.Console::WriteLine(string)
// [19 9 - 19 10]
IL_0014: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname instance void
.ctor() cil managed
{
.maxstack 8
IL_0000: ldarg.0 // this
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
.method private hidebysig static specialname rtspecialname void
.cctor() cil managed
{
.maxstack 8
// [11 9 - 11 47]
IL_0000: ldstr "a"
IL_0005: stsfld string ConsoleApp4.Program::a
IL_000a: ret
} // end of method Program::.cctor
} // end of class ConsoleApp4.Program
对于静态字符串,它的行为符合我的预期。而不是 const 它在堆栈上加载了一个新值......事实上,它在这里查看 ldstr 操作码
将新对象引用推送到存储在元数据中的字符串文字
我在这里读过
现在,无论在代码中何处引用 myInt,MSIL 都无需执行“ldloc.0”来从变量中获取值,而是将硬编码到 MSIL 中的常量值加载。因此,使用常量通常具有较小的性能和内存优势。但是,为了使用它们,您必须在编译时获得变量的值,以及在编译时对该常量的任何引用,即使它们在一个不同的组件,将进行此替换。
如果您知道编译时的值,常量肯定是一个有用的工具。如果你不这样做,但想确保你的变量只设置一次,你可以使用 C# 中的 readonly 关键字(在 MSIL 中映射为 initonly)来指示变量的值只能在构造函数中设置;之后,更改它是错误的。这通常在字段有助于确定类的身份时使用,并且通常设置为等于构造函数参数。
但是我为什么要体验更好的性能呢?(即使考虑到它是相当可追溯的)?内存占用呢?
慕勒3428872
茅侃侃
随时随地看视频慕课网APP
相关分类