C#重构:解析以逗号分隔的字符串[] arg

时间:2010-02-09 04:53:14

标签: c# arrays

好吧,让我们说有这个:

string productUidsPostValue = 
    "693C850B-2B0B-4429-98F8-AE99E92991A8,F37858BD-22E5-4077-BADD-9AFCDCC92628";

我想以最简单的方式将其变成List。当然,productUidsPostValue中的字符串如果有效Guid,则需要强类型为Guid s。这是我写的代码。当然可以重构或减少,对吧?

if (string.IsNullOrEmpty(productUidsPostValue))
{
    throw new InvalidOperationException
        ("this.Request.Form['CheckoutProductUids'] cannot be null or empty.");
}

var seperatedUids = productUidsPostValue.Split(',');

var productUids = new List<Guid>(seperatedUids.Length);

Guid guid;

foreach (var productUid in seperatedUids)
{
      if (!GuidHelper.TryParse(productUid, out guid))
      {
            productUids.Add(guid);
      }
}

7 个答案:

答案 0 :(得分:1)

这是我能想到的最短代码,前提是 productUidsPostValue 正确形成(Guid格式正确)。

  string productUidsPostValue = "693C850B-2B0B-4429-98F8-AE99E92991A8,F37858BD-22E5-4077-BADD-9AFCDCC92628";
  List<Guid> seperatedUids = (from guid in productUidsPostValue.Split(',') select new Guid(guid)).ToList();

答案 1 :(得分:1)

你可以这样做:

return productUidsPostValue.Split(',')
    .Where(productUid => { Guid tmp; return GuidHelper.TryParse(productUid, out tmp); })
    .Select(validProductUid => new Guid(validProductUid))
    .ToList();

哪个更有文化,但我不喜欢那里的try parse方法的味道。

就个人而言,我会尝试将一些GuidHelper.TryParse代码重构为另一种扩展方法,例如:

public static Guid? ParseToNullableGuid(this string stringToParse)
{
    Guid? val = null;

    if(String.IsNullOrEmpty(stringToParse))
        return val;

    var guidPattern = @"[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{8}";
    var validGuid = new Regex(guidPattern, RegexOptions.Compiled);

    if (!validGuid.Match(stringToParse).Success)
        return val;

    try
    {
         val = new Guid(stringToParse);
    }
    catch(FormatException) { }

    return val;
}

然后你可以做更多的事情:

return productUidsPostValue.Split(',')
    .Select(uid => uid.ParseToNullableGuid())
    .Where(uid => uid.HasValue)
    .Select(uid => uid.Value)
    .ToList();

对于奖励积分,您可以在扩展方法中进行更多测试,例如执行string.indexof测试,以保存基于异常的编程,至少比现有的多一点。

答案 2 :(得分:0)

看起来很干净(简单)对我来说。你有什么代码味道吗?

如果你弄清楚C#等效的Ruby的收集(你已经省略了guid验证部分,你可以使代码更简洁一点)

guidStrings.split(',').collect{|each_guid|  
   Guid.new(each_guid)
}

答案 3 :(得分:0)

这是我能做的最短的事情而不会变成不可读的代码。 PS。原始代码无法检查TryParse是否成功,并且它也抛出了错误的异常类型。

if (string.IsNullOrEmpty(productUidsPostValue))
    throw new ArgumentNullException("this.Request.Form['CheckoutProductUids']");

foreach (var productUid in productUidsPostValue.Split(','))
{
    Guid guid;
    if (GuidHelper.TryParse(productUid, out guid))
        productUids.Add(guid);
}

答案 4 :(得分:0)

您可以使用LINQ:

Guid guid;
List<Guid> productUids = productUidsPostValue.Split(',')
    .Select(s => {guid = Guid.Empty; GuidHelper.TryParse(s, out guid); return guid;});

答案 5 :(得分:0)

如果您使用的是.NET 4.0,则可以使用新的Guid.TryParse。否则,请在下面的代码中使用GuidHelper.TryParse

string productUidsPostValue = "693C850B-2B0B-4429-98F8-AE99E92991A8,F37858BD-22E5-4077-BADD-9AFCDCC92628,F37858BD-22E5-4077-BADD-9AFCDCC9262-XYZ";
var query = productUidsPostValue.Split(',')
                .Select(s => {
                    Guid result;
                    return Guid.TryParse(s, out result) ? 
                                                (Guid?)result : (Guid?)null;
                })
                .Where(g => g.HasValue)
                .Select(g => g.Value)
                .ToList();

答案 6 :(得分:0)

这个以逗号分隔的字符串不太可能是人为输入,所以我不建议在逗号分隔列表中优雅地处理单独的错误guid条目。

如果你在这里安全地处理错误的输入付出了太多的努力,你实际上是在寻找问题。例如,客户端代码可能提供错误的输入字符串,您可以优雅地将其视为良好的输入,但具有不同的含义。

相反,如果无法解析任何项目的话,我建议一次性对来自整个字符串的guid解析构造函数的任何异常失败,这样你就可以得到最干净的代码。