2010-02-09 44 views
0

好吧,让我们有说有这样的:C#重构:解析逗号分隔的String [] ARG

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

我想变成一个List这个可能的最简单的方法。当然,productUidsPostValue中的字符串必须强制输入为Guid s,前提是它们的有效性为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); 
     } 
} 

回答

0

看起来很干净(对我来说简单)。你会嗅到什么?

,如果你弄清楚你可以使代码更简洁一点的C#相当于Ruby的收集(我省略了GUID验证一部分,尽管你需要它)

guidStrings.split(',').collect{|each_guid| 
    Guid.new(each_guid) 
} 
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); 
} 
0

你可以使用LINQ:

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

有没有原因被改变了? – 2010-02-09 05:08:50

+0

考虑“693C850B-2B0B-4429-98F8-AE99E92991A8,F37858BD-22E5-4077-BADD-9AFCDCC92628的输入值,这不是Guid,但会导致Guid.Empty被添加到列表中” – 2010-02-09 05:16:53

+0

@ Travis:我想通过添加空Guid比添加已添加到列表中的最后一个值要好。同样,如果他的列表中的第一个值不是有效的Guid,他的版本也会添加一个空值。 – 2010-02-09 05:20:36

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

你可以做这样的事情:

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

哪个更识字,但我不喜欢尝试解析方法的味道在里面。

就个人而言,我会尝试重构你的一些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测试,以保存基于异常的编程,至少比这已经多了一点。

+0

关于-1的任何解释? – Khanzor 2010-02-09 21:56:17

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(); 
0

这个逗号分隔的字符串不太可能是人类输入,所以我不会推荐在逗号分隔列表中正确处理单独的错误的guid条目。

如果您在这里安全地处理错误的输入花费了太多的精力,那么您实际上是在寻找问题。例如,客户端代码可能会提供错误的输入字符串,并且您优雅地将其视为良好的输入,但具有不同的含义。如果任何项目无法解析,那么我会建议对来自guid解析构造函数的任何异常一次性失败,因此您可以想出最干净的代码。