C# '++' 运算符与 ToString() 结合使用

C# '++' Operator in conjunction with ToString()

我需要在 linqpad 中对此进行验证,但此代码第一次评估为 0。为什么在 C# 中会出现这种情况?

var integer = 0;
while(true){
    var @string = integer++.ToString();
    Console.WriteLine(@string);
}

我也验证了先求值为1。

var integer = 0;
while(true){
    var @string = (++integer).ToString();
    Console.WriteLine(@string);
}

我明白++x和x++的区别了。只是期待它执行 x++,然后调用 ToString()。

https://msdn.microsoft.com/en-us/library/6a71f45d.aspx

++的后缀版本returns整数的值然后递增,而++的前缀版本然后returns递增。因此,在这两种情况下,您都是在返回值上调用 ToString,但运算符的位置决定了要返回哪个值。

后缀和前缀这两个运算符都充当函数。他们 return 对其参数执行操作后的值,在本例中为 integer。它看起来非常规,但这就是它正在做的事情。

所以基本上,你在做:

var @string = postfixplusplus(integer).ToString();

希望这种思路能说明一点。

我对post自增运算符的理解是,它首先保存变量的值(在本例中为i),自增i,然后使用保存的值(在此示例中,在对 ToString()).

的调用中

此代码:

int i = 5;
string s = i++.ToString();

相当于:

int i = 5;
int temp = i;
i = i + 1;
var s = temp.ToString();

可以使用LinqPad或者其他工具(ILSpy等)查看IL:

IL_0000:  nop         
IL_0001:  ldc.i4.5    
IL_0002:  stloc.0     // i
IL_0003:  ldloc.0     // i
IL_0004:  dup         
IL_0005:  ldc.i4.1    
IL_0006:  add         
IL_0007:  stloc.0     // i
IL_0008:  stloc.2     // CS[=12=][=12=]00
IL_0009:  ldloca.s    02 // CS[=12=][=12=]00
IL_000B:  call        System.Int32.ToString
IL_0010:  stloc.1     // s
IL_0011:  ret         

这里有一个 blog post by Eric Lippert 包含更多信息

从根本上说,i++.ToString()++ 运算符的行为与调用任何其他以 i 作为参数的函数时的行为没有区别。例如,如果您调用 SomeFunction(i++).

,您完全希望传递 i 的原始值

例如,考虑一个扩展方法:

public static class GoofyExtensions
{
    public static string Frob(this int x)
    {
        return x.ToString();
    }
}

现在,可以像调用实例方法一样调用它了:

var s = i++.Frob();

编译器将其转换为对静态 Frob 方法的调用:

var s = GoofyExtensions.Frob(i++);

发现 i++.Frob() 返回的值与 i++.ToString() 不同。

这里的重点是,虽然ToString()是一个没有参数的方法,但是在内部所有的实例方法都有一个隐含的参数:实例。如果检查生成的 MSIL,您会看到对实例的引用作为参数传递给所有实例方法。所以 i.ToString() 实际上是对 Int32.ToString(i).

的调用