3

我有这个代码...

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

TryParseStatement 之后,i变量中的值被覆盖(as zero)并且我之前的值丢失了。

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

4

5 回答 5

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"
}
于 2013-05-22T07:32:26.347 回答
5

这不是错误,如果转换失败,则返回零。在这种情况下,函数的返回值为 false。

当此方法返回时,如果转换成功,则包含与 s 中包含的数字等效的 32 位有符号整数值,如果转换失败,则返回零。如果 s 参数为空、格式不正确或表示小于 MinValue 或大于 MaxValue 的数字,则转换失败。此参数未初始化传递。

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

于 2013-05-22T07:27:33.843 回答
2

出(C# 参考)

虽然作为输出参数传递的变量在传递之前不需要初始化,但调用方法需要在方法返回之前赋值

Int32.Parse初始化它default(int)为零。

s当此方法返回时,如果转换成功,则包含与 中包含的数字等效的 32 位有符号整数值,如果转换失败,则返回零

于 2013-05-22T07:32:40.553 回答
1

这不是一个错误,因为它是一个输出参数。作为练习,尝试编写不设置 out 参数值的 C#。(提示:这是不可能的)因此您观察到的结果是唯一合乎逻辑的结果 - out 变量没有“重新初始化”,它只是简单地初始化。

如果已编写 TryParse 以获取 ref int,那么您想要的将是可能的。我个人认为 int 在这里更好。

于 2013-05-22T07:35:59.943 回答
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;

于 2013-05-22T07:29:24.663 回答