我有这个代码...
var i = int.MinValue;
var s = string.Empty;
int.TryParse(s, out i);
在TryParse
Statement 之后,i
变量中的值被覆盖(as zero
)并且我之前的值丢失了。
这是一个错误吗?如果否,是否有任何实现细节说明为什么需要重新初始化作为out
参数传递的变量
的全部意义out
在于它保证(嗯,至少在 C# 级别......而不是 IL 级别)覆盖这个值。这样做的目的是避免不必要的分配,同时允许“明确分配”。例如:
int i; // note: not assigned
var s = string.Empty;
// here "i" is not "definitely assigned"
int.TryParse(s, out i);
// here "i" is "definitely assigned"
这个想法是您使用返回值,例如:
if(int.TryParse(s, out i)) {
// here "i" makes sense; feel free to use it
} else {
// here you shouldn't use the value of "i"
}
在您的具体情况下,您可以重新订购:
if(!int.TryParse(s, out i)) i = int.MinValue;
特别要注意(至少在 C# 中)方法必须赋值,并且不能使用传入的值;例如:
static void Foo(out int i) {
return; // error: hasn't assigned to i
}
static void Bar(out int i) {
int j = i; // error: cannot read from "i" until Bar has assigned a value
i = j;
}
static void Baz(out int i) {
i = 0; // note that after this assignment, code in Baz can read from "i"
}
对比ref
;传ref
值时,需要在调用者处明确赋值。该方法本身可能会或可能不会查看传入的值(根据它的选择),并且可能会或可能不会分配一个新值(根据它的选择)。例如:
int i;
SomeMethod(ref i); // illegal - "i" is not definitely assigned
int i = 0;
SomeMethod(ref i); // legal
和:
static void Foo(ref int i) {
return; // perfectly legal to not look at "i" and/or not assign "i"
}
static void Foo(ref int i) {
i = i + 1; // perfectly legal to look at "i" and/or assign "i"
}
这不是错误,如果转换失败,则返回零。在这种情况下,函数的返回值为 false。
当此方法返回时,如果转换成功,则包含与 s 中包含的数字等效的 32 位有符号整数值,如果转换失败,则返回零。如果 s 参数为空、格式不正确或表示小于 MinValue 或大于 MaxValue 的数字,则转换失败。此参数未初始化传递。
虽然作为输出参数传递的变量在传递之前不需要初始化,但调用方法需要在方法返回之前赋值。
Int32.Parse
初始化它default(int)
为零。
s
当此方法返回时,如果转换成功,则包含与 中包含的数字等效的 32 位有符号整数值,如果转换失败,则返回零。
这不是一个错误,因为它是一个输出参数。作为练习,尝试编写不设置 out 参数值的 C#。(提示:这是不可能的)因此您观察到的结果是唯一合乎逻辑的结果 - out 变量没有“重新初始化”,它只是简单地初始化。
如果已编写 TryParse 以获取 ref int,那么您想要的将是可能的。我个人认为 int 在这里更好。
不,如果您将设置为变量 s 值(例如“3”),这不是错误
var s = "3";
你将得到 i 的值将等于 3
如果您设置 string.Empty 它将为零,这是默认实现
你可以看看反编译的实现代码
internal static unsafe bool TryParseInt32(string s, NumberStyles style, NumberFormatInfo info, out int result)
{
byte* stackBuffer = stackalloc byte[114];
Number.NumberBuffer number = new Number.NumberBuffer(stackBuffer);
result = 0;
if (!Number.TryStringToNumber(s, style, ref number, info, false))
return false;
if ((style & NumberStyles.AllowHexSpecifier) != NumberStyles.None)
{
if (!Number.HexNumberToInt32(ref number, ref result))
return false;
}
else if (!Number.NumberToInt32(ref number, ref result))
return false;
return true;
}
结果设置为0;