如何安全地解析字符串?最佳实践是什么?

7
C#中类型转换的最佳实践是什么?
   int temp=System.ConvertToInt32(Request.QueryString["Id"]);
    if (temp!=null)
      { // logic goes here }

如果Id不小心变成了'abc',这个操作会失败。

请建议使用三元运算符和其他单行语句,除了if else语句(例如使用单行三元运算符)。此外,你们更喜欢TryParse还是Convert呢?为什么?请发表你的看法。


1
以上代码中,Temp永远不会为空。 - Rune FS
7个回答

7
TryParse有一个明显的优点,即在失败的情况下,它会返回false而不是抛出异常。
标准模式通常是这样的:
int value;
if (int.TryParse(Request.QueryString["Id"], out value))
{
    // Use value
}
else
{
    // Do whatever you want on failure
}

现在,还值得注意的是,您可以为 int.TryParse 提供一个 IFormatProvider 和一个 NumberStyles - 例如,如果这确实是一个自动生成的 ID(而不是用户输入的 ID),您可能希望将 CultureInfo.InvariantCulture 指定为 IFormatProvider
如果您想有效地拥有“默认值”,您可以编写一个像这样的辅助方法:
public static int? NullableTryParseInt32(string text)
{
    int value;
    return int.TryParse(text, out value) ? value : (int?) null;
}

您可以像这样使用它:
int value = NullableTryParseInt32(text) ?? 10;

当然,您也可以编写一个带有默认值的方法 :)

嗨Jon,谢谢回复。您怎么使用三元运算符来编写该语句?此外,“out”每次评估(匹配或不匹配)时都会被初始化,这不是吗?我们不应该因此避免尝试解析吗? - Zo Has
@Popo:是的,out参数无论如何都会被初始化,但为什么你要因此避免使用TryParse呢?我已经添加了另外几个选项来简化在默认值有意义的情况下的操作,但很多时候第一种形式确实是最好的选择。 - Jon Skeet
谢谢Jon,TryParse只会返回true/false吗?我能像Sunrisas在使用Convert时那样检查TryParse中的异常吗? - Zo Has

1

你有两种方法可以做到这一点

int i;
if (Int32.TryParse(Request.QueryString["Id"], out i))
{
}

或者您可以这样做:

try
{
     Convert.ToInt32(Request.QueryString["Id"]);
}
catch (FormatException ex)
{
   // The field Id it's not convertible
}
catch (Exception ex)
{
   // It could throw also ArgumentException or OverflowException
}

嗨sinrisas,我该如何在tryParse中捕获异常? - Zo Has
你可以将它放入try catch语句中。据我所知,TryParse可能抛出的唯一异常是ArgumentException,但在这种情况下,我想你总是会将一个字符串传递给它,因此你永远不会遇到这样的异常。 TryParse背后的思想并不是使用try catch语句,而是根据转换的成功与否返回true或false。 - Sergio Rosas

1

当涉及到解决有几个类似解决方案的问题时,我也会尝试找到一个能够清晰地表达我想要实现的代码读者的解决方案。在我看来,在这种特定情况下,这意味着选择 .TryParse。

使用 TryParse 告诉读者您不能保证输入是有效的(如果是,则使用 parse)。而且,由于您实际上正在尝试将输入解析为 int,因此您可以让代码读取您的意图。


1

1

使用TryParse是最好的选择。从转换方法中捕获异常是一项昂贵的操作。当然,TryParse只接受字符串,而Convert.ToInt32将接受对象并可以执行转换(解包、从长整型/双精度浮点数向下转换)以及解析。


1

关于三元运算符方面的问题:

我对使用三元运算符的建议是,如果您对所涉及的代码不熟悉,无法自然地阅读它,请不要使用它们。简洁使熟悉的更加熟悉,陌生的更加陌生。

当您已经足够理解这里关于TryParse的讨论,以至于您甚至不需要再有意识地思考它时,从if-else到?:的转换将不仅是微不足道的,而且是自动的。在那之前,您只会增加自己的困惑。

当我对某些东西不熟悉时,我首先会使用“婴儿语言”编写代码,学习新事物,然后将其整合到我的正常更简洁的风格中。


0
使用 int 类的 TryParse 方法。
int temp;
if (int.TryParse(Request.QueryString["Id"], out temp)
  { // logic goes here }

如果id不包含数字,TryParse将返回false。
更新:更改为显示int.TryParse。

字符串似乎没有适用于我的TryParse方法...你确定你不是想输入int.TryParse吗? - Chris
这里不应该关注输出温度吗? - Zo Has
我认为你想使用int.TryParse,因为没有string.TryParse,毕竟你为什么要将一个字符串解析成一个字符串;-) - Ben Robinson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接