2009-07-17 52 views
10

如果我运行此C#代码为什么Int32.TryParse在无法转换时重置out参数?

int realInt = 3; 
string foo = "bar"; 
Int32.TryParse(foo, out realInt); 

Console.WriteLine(realInt); 
Console.Read(); 

我得到0。而且我想知道为什么!因为我找不到任何原因。这迫使我为每个解析创建临时变量。所以,请!伟大的宇宙编码者,赐教!

+0

我格式化代码为您服务。下一次,如果您不确定如何在MarkDown编辑器中设置格式,请使用文本区域上方的小工具栏。有一个代码格式化选项。 – OregonGhost 2009-07-17 08:31:40

+0

感谢您的帮助=) – 2009-07-17 08:49:00

回答

33

它是“out”,而不是“ref”。在该方法内部,具有来分配它(不先读取它)以满足“out”的含义。

实际上,“out”是一个语言问题(不是框架之一) - 所以托管的C++实现可能会忽略这个......但是它更符合它的要求。

实际上,如果该方法返回false,则不应该查看该值;将其视为垃圾直到下一次分配。它声明返回0,但这是很少有用的。


此外 - 如果它没有这样做(即如果它保存了值);这个打印:

int i; 
int.TryParse("gibber", out i); 
Console.WriteLine(i); 

这是完全有效的C#...所以它打印什么?

+2

*为什么*它是这样的解释,以便您可以断言在TryParse调用后的任何代码中变量* always *都已设置,即使变量在代码的前面没有初始化(所以编译器在`TryParse`调用之后使用该变量时不会引发错误;尝试对使用`ref`关键字的函数执行相同操作。) – Blixt 2009-07-17 08:16:42

6

The Int32.TryParse Method (String, Int32) doc说:

一个数字的字符串表示形式转换为它的32位带符号整数等效。返回值指示转换是否成功。

结果

类型:System.Int32

此方法返回时,包含32位带符号整数的值等效于包含在S中的号码,如果转换成功,或者零,如果转换失败。如果s参数为空引用(在Visual Basic中为Nothing),格式不正确,或者表示小于MinValue或大于MaxValue的数字,则转换将失败。此参数未经初始化传递。

+0

@Luke - look以粗体显示... – 2009-07-17 08:08:02

0

因为(至少在C#中)带有一个或多个输出参数的方法必须保证它们回写给它们。这样,在将方法作为参数传递给方法之前,您不需要在方法中初始化本地字段。

0

我的猜测是,这是在C#规范的一部分:

10.5.1.3输出参数 ... 在方法内部,就像一个局部变量,输出参数最初考虑>未分配必须在使用其值之前明确分配。

在方法返回之前,方法的每个输出参数都必须明确赋值。

如果是这种情况,您不应该依赖结果值。

0

由于TryParse的第二个参数是out参数,因此TryParse方法被强制初始化参数。如果参数是ref而不是out,您将得到您想要的行为。但是,由于TryParse方法只需要输出一个数字,并且不会获得任何数字,因此输入out是参数的正确选择。

2

因为这是'out'合同的工作方式。每当你将一个out参数传递给一个函数时,它的函数的责任就是初始化它。

1

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 
} 

我个人认为后者是更好的选择。

4

由于该参数是一个输出参数,所以当您声明它时,您不必初始化realInt,因为编译器可以看到您将它传递给一个保证将其设置为某事的方法(因为的“出”)。

现在,因为它是一个输出参数,所以需要TryParse将其设置为某个值。它将它设置为0,因为这是C#中大多数情况下int的默认值。

你可以写为:

int realInt; 
string foo="bar"; 
if(int.TryParse(foo,out realInt)==false) 
{ 
    realInt=3; 
} 
1
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; 
    } 
} 
相关问题