【问题标题】:How to properly put statements inside a try-catch block?如何正确地将语句放入 try-catch 块中?
【发布时间】:2013-11-14 03:24:56
【问题描述】:

我需要一个接一个地执行很多语句,并且我需要当单个语句抛出异常时程序流继续执行下一个语句,例如

double a = Double.Parse("2.5");
double b = Double.Parse("ADFBBG");
Geometry g = Geometry.Parse("M150,0L75,200 225,200z");

所有语句都必须执行,所以我需要一种级联的 try-catch 块:

double a, b;
Geometry g;

try
{
   a = Double.Parse("2.5");
}
catch
{}

try
{
   b = Double.Parse("ADFBBG");
}
catch
{}

try
{
   g = Geometry.Parse("M150,0L75,200 225,200z");
}
catch
{}

显然,这不是编写我的程序的最优雅的方式。 有没有更好的方法(更优雅,不会显着降低性能)?

我尝试以这种方式使用Func<TResult> 委托:

我写了如下方法:

T Try<T>(Func<T> func)
{
    try
    {
        return func();
    }
    catch
    {
        return default(T);
    }
}

所以我可以这样使用它:

double x = Try(() => Double.Parse("77"));
Geometry g = Try(() => Geometry.Parse("M150,0L75,200 225,200z"));

其他解决方案?

【问题讨论】:

  • 我希望您的问题不是真正基于将字符串解析为双精度数,因为您知道,您可以简单地使用 TryParse 而不是 Parse 绕过引发异常的问题。
  • @Steve 当然不是……
  • 您需要一个更好的示例,否则您将得到的只是TryParse 的答案。 :-)
  • 您的 Try 函数是一个很好的解决方案。去吧。
  • +1 用于尝试功能。我想这是最好的解决方案,继续吧。

标签: c# exception try-catch func


【解决方案1】:

使用Double.TryParse

它返回一个值,指示转换是否成功。所以你可以通过以下方式使用它:

double converted;
bool success = Double.TryParse(value, out converted);

if (success)
{
    // Do whatever you want
    // The converted value is in the variable 'covnerted'
}

【讨论】:

    【解决方案2】:

    您似乎并不关心哪个解析失败,而只需要一个默认值是失败的情况?如果是这样,首先将您的 vars 初始化为默认值,然后在单个 try-catch 中解析:

    double a=0.0, b=0.0;
    Geometry g = new Geometry();
    
    try
    {
       a = Double.Parse("2.5");
       b = Double.Parse("ADFBBG");
       g = Geometry.Parse("M150,0L75,200 225,200z");
    }
    catch
    {
        //At least mark that conversion was not succesful
    }
    

    Try-catch 只会在抛出异常时给您带来性能损失。如果一切顺利,try-catch 的影响是微乎其微的。看到这个question 比您发布的代码更优雅一点,但至少更简洁。

    使用 TryParse 的替代方法

    double a=0.0, b=0.0;
    Geometry g = new Geometry();
    
    Double.TryParse("2.5", out a);
    Double.TryParse("ADFBBG", out b);
    Geometry.TryParse("M150,0L75,200 225,200z", out g);
    

    但有一点需要注意:Geometry 没有实现 TryParse...(假设您使用 System.Windows.Media.Geometry

    这让我明白了:

    • 使用您的 Try 函数,不会减少开销但很干净
    • 首先验证字符串。消除了 try 的开销,但在解析时引入了运行时开销。

    无论哪种方式:验证用户输入都是有代价的。

    回答主要问题:如何正确地将语句放入 try-catch 块中? 如果您不关心哪个语句失败:1 try-catch。

    但是:如果第一条语句失败,则不会执行另一条语句。但是,您的系统已经处于失败/损坏状态。进一步处理会产生正确的结果吗? (怀疑)

    【讨论】:

      【解决方案3】:

      TryParse 更可取,因为您在抛出和捕获异常时没有性能损失。

      上述代码中还有一个不准确之处——解析的“0”和默认值(T)之间没有区别。

      代码比你的快

      public static class StringExt
          {
              public static double ParseDouble(this string value)
              {
                  double result;
                  Double.TryParse(value, out result);
                  return result;
              }
      
          }
      

      【讨论】:

        【解决方案4】:

        几天前我已经回答了一个类似的问题。如果您有一组字符串值,则可以使用扩展方法的强大功能来做到这一点。

        static public IEnumerable<double> ConvertToDouble(this IEnumerable<string> source)
        {
            double x = 0;
            var result = source.Where(str => Double.TryParse(str, out x))
                                .Select (str => x);
        
            return result;      
        }
        

        所以把所有东西放在一个集合中,然后使用.AsEnumerable(),然后使用ConvertToDouble()扩展方法。所有无法解析的内容都会被忽略,无一例外,结果是IEnumerable&lt;Double&gt;

        原答案:Convert List<string> to List<int> in C#

        /edit: 否决投票者愿意解释吗? OP 没有澄清,为什么他想使用 try catch,也没有解释在发生异常时必须做什么。 Hance 我假设他不想做任何事情以防引发异常。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-09-08
          • 1970-01-01
          • 2016-03-15
          • 2019-08-13
          • 2016-03-24
          • 2015-08-26
          • 1970-01-01
          相关资源
          最近更新 更多