0

此代码检索日志文件的行并尝试在分隔字段之一中查找日期。哪个字符是分隔符可能会有所不同,并且可以在哪个字段中找到日期也会有所不同。它也可以写成不同的日期格式或从 Unix 纪元时间经过的毫秒数。它从列表的底部开始,如果没有找到,它会递归地向上移动,直到没有更多的行可以读取。因此,最简单、最易读的方法(在我看来)是使用嵌套的 try-catch 块,但鉴于它也是一种递归方法,理论上应该会降低性能吗?这是一个糟糕的代码吗?

我可以将一堆 if-else 块与 DateTime.TryParse 一起使用,并为结果添加额外的变量,但这会让我的眼睛流血。代码的可读性是否证明嵌套的 try-catch 块用于流控制?

static DateTime? Search(List<string> lines)
{
    if (lines.Count == 0)
    {
        return null;
    }

    DateTime? date = null;
    string dateField;

    try
    {
        dateField = lines.Last().Split(';')[18].Trim('\'').Trim();
        date = DateTime.ParseExact(dateField, "MM'/'dd'/'yy HH:mm:ss", null, DateTimeStyles.AllowWhiteSpaces);
    }
    catch (Exception)
    {
        try
        {
            dateField = lines.Last().Split(';')[19].Trim('\'').Trim();
            date = DateTime.ParseExact(dateField, "MM'/'dd'/'yy HH:mm:ss", null, DateTimeStyles.AllowWhiteSpaces);
        }
        catch (Exception)
        {
            try
            {
                dateField = lines.Last().Split(':')[9].Split('=')[1].Trim();
                date = FromUnixEpochTime(long.Parse(dateField));
            }
            catch (Exception)
            {
                try
                {
                    dateField = lines.Last().Split(':')[12].Split('=')[1].Trim();
                    date = FromUnixEpochTime(long.Parse(dateField));
                }
                catch (Exception)
                {
                    try
                    {
                        dateField = lines.Last().Split(':')[19].Trim('\'').Trim();
                        date = DateTime.ParseExact(dateField, "MM'/'dd'/'yy HH", null, DateTimeStyles.AllowWhiteSpaces);
                    }
                    catch (Exception)
                    {
                        lines.RemoveAt(lines.Count - 1);
                        date = Search(lines);
                    }
                }
            }
        }
    }

    return date;
}
4

3 回答 3

2

当您打算处理同一部分中的代码时,您永远不应该抛出异常。这使得调试异常成为一场噩梦。我的建议是有一个调用子方法的主要方法来尝试每种类型 - 如果值不是你所期望的 - 移动到下一个。

    public DateTime? GetValue()
    {
        DateTime? value = null;

        // Regular way
        value = GetValueImpl1();

        if (value != null)
            return value;

        // Fall back 1
        value = GetValueImpl2();
        if (value != null)
            return value;

        // Fall back 2
        value = GetValueImpl3();
        if (value != null)
            return value;
        return null;
    }
    private DateTime? GetValueImpl1()
    {
        return new DateTime();
    }
    private DateTime? GetValueImpl2()
    {
        return new DateTime();
    }
    private DateTime? GetValueImpl3()
    {
        return new DateTime();
    }
于 2013-04-14T14:31:48.297 回答
2

我知道你已经排除了他们,但我会选择

TryParse

TryParseExact 

(虽然 AFAIK 在内部他们只是使用 try-catch .. 但你的代码变得更具可读性)

我会借用 TryParse 等背后的想法,并按照 .. 的方式做一些事情(见下文)

我认为这种风格将每个策略分开并使其更易于维护,因为每个策略周围的“噪音”(即异常捕获)更少

(我在示例策略中允许重复,但其中一些也可以重新考虑)

干杯

斯图

static DateTime? Search(List<string> lines)
{
    if (lines.Count == 0)
    {
        return null;
    }

    DateTime parsedDate;

    // the first successful strategy will 'short circuit' the rest so they don't run
    if(TryGetDateStrategy1(lines, out parsedDate)
        || TryGetDateStrategy2(lines, out parsedDate)
        || etc. etc.) 
    {
        return parsedDate;
    }
    return null;
}

private static bool TryGetDateStrategy1(List<string> lines, out DateTime? date)
{
    var dateField = lines.Last().Split(';')[19].Trim('\'').Trim();
    DateTime parsedDate;
    if (DateTime.TryParseExact(dateField, "MM'/'dd'/'yy HH:mm:ss", null, DateTimeStyles.AllowWhiteSpaces,out date))
    {
        date = parsedDate;
        return true;
    }
    return false;
}
private static bool  TryGetDateStrategy2(List<string> lines, out DateTime? date)
{
    var dateField = lines.Last().Split(';')[18].Trim('\'').Trim();
    DateTime parsedDate;
    if (DateTime.TryParseExact(dateField, "MM'/'dd'/'yy HH:mm:ss", null, DateTimeStyles.AllowWhiteSpaces, out date))
    {
        date = parsedDate;
        return true;
    }
    return null;
}
于 2013-04-14T14:51:45.167 回答
0

例外适用于“特殊”情况。它们的性能时间很差,因为它们的处理方式与普通代码不同。网上有很多解释解释了为什么异常会减慢代码的速度。

使用 tryParse 方法检查您的数据是否为日期,然后使用 if then else 语句会更有效,并且可以说更简洁和可读。

也使用字符串常量而不是再次输入日期格式。这会产生更难维护的代码。

作为事后的想法,您可以使用 if 语句:

if (tryParse(...)){
   return Parse(...);
}

if (tryParse(...)){
   return Parse(...);
}

return null;

这将是没有嵌套的最可读的,并且可以以更可读的方式进行注释

于 2013-04-14T14:30:23.943 回答