int.TryParse会覆盖作为out参数传递的整数的值

时间:2013-05-22 07:24:35

标签: .net c#-4.0 .net-4.0

我有这段代码......

var i = int.MinValue;
var s = string.Empty;
int.TryParse(s, out i);

TryParse语句之后,i变量中的值被覆盖(as zero),之前的值丢失了。

这是一个错误吗?如果否,是否有任何实现细节,说明为什么必须重新初始化作为out参数传递的变量

5 个答案:

答案 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的数字。这个参数是   没有初始化。

http://msdn.microsoft.com/en-us/library/f02979c7.aspx

答案 2 :(得分:2)

out (C# Reference)

  

尽管作为out参数传递的变量不需要初始化   在传递之前,调用方法需要分配一个   方法返回前的值

Int32.Parsedefault(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;