如果我运行这段C#代码
int realInt = 3;
string foo = "bar";
Int32.TryParse(foo, out realInt);
Console.WriteLine(realInt);
Console.Read();
我得到了0。我想知道为什么!因为我找不到任何原因。这迫使我为每个解析创建临时变量。所以,请宇宙中伟大的程序员们,启发我吧!
如果我运行这段C#代码
int realInt = 3;
string foo = "bar";
Int32.TryParse(foo, out realInt);
Console.WriteLine(realInt);
Console.Read();
我得到了0。我想知道为什么!因为我找不到任何原因。这迫使我为每个解析创建临时变量。所以,请宇宙中伟大的程序员们,启发我吧!
应该使用 "out",而不是 "ref"。在方法内部,为满足 "out" 的含义,它必须将其赋值(而不先读取)。
实际上,“out”是一项语言规定(而非框架规定),因此,托管 C++ 实现可能会忽略此规定......但遵循此规定更加一致。
事实上,如果该方法返回 false,则您根本不应查看该值;直到下一次分配之前,将其视为垃圾。虽然它被声明为返回 0,但这很少有用。
另外,如果它没有这样做(即保留该值),那么这将打印什么:
int i;
int.TryParse("gibber", out i);
Console.WriteLine(i);
这是完全有效的C#代码...那么它会输出什么?
Int32.TryParse方法 (String, Int32) 文档 中提到:
将数字的字符串表示转换为其 32 位有符号整数等效项。返回值指示转换是否成功。
result
类型:System.Int32
当此方法返回时,如果转换成功,则包含与 s 参数中包含的数字等效的 32 位有符号整数值,如果转换失败,则为零。 如果 s 参数是 null 引用(Visual Basic 中的 Nothing),格式不正确或表示小于 MinValue 或大于 MaxValue 的数字,则转换失败。 此参数未初始化传递。
int realInt;
string foo="bar";
if(int.TryParse(foo,out realInt)==false)
{
realInt=3;
}
这是“out”合同的工作原理。每当您将一个out
参数传递给函数时,函数负责初始化它。
关于 Int32.TryParse 的 MSDN 文档指出,如果转换失败,则结果将始终返回 0。
通常情况下,您应该使用临时结果变量,例如:
int value;
bool succeeded = Int32.TryParse("astring", out value);
if (succeeded)
{
// use value in some way
}
或者你可以将整个方法用if语句包装起来
int value;
if (Int32.TryParse("astring", out value))
{
// use value in some way
}
个人而言,我认为后者是更好的选择。
public static class IntHelper
{
public static bool TryParse(string s, ref int outValue)
{
int newValue;
bool ret = int.TryParse(s, out newValue);
if (ret) outValue = newValue;
return ret;
}
}
我猜这是C#规范的一部分:
10.5.1.3 输出参数 ... 在方法内部,就像本地变量一样,输出参数最初被认为是未赋值的,在使用其值之前必须明确赋值。
方法的每个输出参数在方法返回之前必须明确赋值。
如果是这种情况,您不应该依赖于结果值。
由于TryParse
的第二个参数是一个out
参数,所以TryParse
方法被强制初始化该参数。如果该参数是ref
而不是out
,则可以获得所需的行为。然而,由于TryParse
方法只需要输出一个数字而不需要获取任何数字作为输入,因此out
是参数的正确选择。
TryParse
调用之后的任何代码中变量都将始终被设置,即使变量在代码中之前没有初始化(因此编译器在您在TryParse
调用后使用变量时不会抛出错误;请尝试使用使用ref
关键字的函数执行相同的操作。) - Blixt