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)
.
的调用
我需要在 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)
.