我有这段代码......
var i = int.MinValue;
var s = string.Empty;
int.TryParse(s, out i);
在TryParse
语句之后,i
变量中的值被覆盖(as zero
),之前的值丢失了。
这是一个错误吗?如果否,是否有任何实现细节,说明为什么必须重新初始化作为out
参数传递的变量
答案 0 :(得分:8)
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"
}
答案 1 :(得分:5)
这不是错误,如果转换失败,则返回零。在这种情况下,函数的返回值将为false。
此方法返回时,包含32位有符号整数值 相当于s中包含的数字,如果转换成功, 如果转换失败,则为零。如果是s,则转换失败 参数为null,格式不正确或表示a 小于MinValue或大于MaxValue的数字。这个参数是 没有初始化。
答案 2 :(得分:2)
尽管作为out参数传递的变量不需要初始化 在传递之前,调用方法需要分配一个 方法返回前的值。
Int32.Parse
将default(int)
初始化为零。
当此方法返回时,包含等同于s
中包含的数字的32位有符号整数值,如果转换成功,或如果转换失败则为零。
答案 3 :(得分:1)
这不是一个bug,因为它是一个out参数。作为练习,尝试编写不设置out参数值的C#。 (提示:这是不可能的)因此,你观察到的结果是唯一合乎逻辑的结果 - out变量不是“重新初始化”,它只是简单的初始化。
如果编写了TryParse以获取ref int,那么你想要的就是可能的。我个人认为int更好。
答案 4 :(得分:0)
如果您将设置为变量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;