我有这个代码:
private static void Tokenize(RichTextLabel Log,string commandString){
Log.Text += "\n&";
int[] tokens = new int[5];
int current = 0;
while (current < commandString.Length){
switch (commandString[current]){
case ' ':
Log.Text += "+";
break;
default:
Log.Text += "_";
break;
}
current++;
}
Log.Text += "\n";
}
当我查看“编译代码”(骑手的 IL 查看器中的低级 C#)时,我知道它在所有情况下都不是完美或准确的。但这就是它产生的结果:
private static void Tokenize(RichTextLabel Log, string commandString)
{
RichTextLabel richTextLabel1 = Log;
richTextLabel1.Text = string.Concat(richTextLabel1.Text, "\n&");
int[] tokens = new int[5];
for (int current = 0; current < commandString.Length; ++current)
{
if (commandString[current] == ' ')
{
RichTextLabel richTextLabel2 = Log;
richTextLabel2.Text = string.Concat(richTextLabel2.Text, "+");
}
else
{
RichTextLabel richTextLabel3 = Log;
richTextLabel3.Text = string.Concat(richTextLabel3.Text, "_");
}
}
RichTextLabel richTextLabel4 = Log;
richTextLabel4.Text = string.Concat(richTextLabel4.Text, "\n");
}
如你所见,它产生了 4 个重复的
RichTextLabel richTextLabel = Log;
我的问题是,这准确吗?如果是这样,为什么需要多次重新引用该对象?
这主要是对正在发生的事情的准确表示,只是我认为该变量实际上并不存在。
12.21.4 复合赋值
形式的操作通过应用二元运算符重载解析 (§12.4.5) 进行处理,就像该操作被编写为x «op»= y
一样。然后,x «op» y
- 如果所选运算符的返回类型可以隐式转换为 x 的类型,则该操作将被计算为
,除了x = x «op» y
仅计算一次 (我的粗体)。x
- 否则,.....操作将被评估为
,其中x = (T)(x «op» y)
是T
的类型,除了x
仅评估一次。x
并且由于编译器不知道
Log
的作用,为了防止 getter 和 setter 可能引用不同的对象,它只是将其缓存在隐藏变量中。
话虽如此,查看 Sharplab 中生成的 IL 会发现使用了 dup
操作码,因此它实际上不是将其缓存在变量中,而是将其缓存在堆栈中。因此,Rider 可能只是生成一个变量,以便在伪 C# 中表示相同的语义。不过,效果和性能应该是相同的,并且您不应期望编译器一定会使用一种形式而不是另一种形式。