【问题标题】:C# Refactoring: Parsing comma-seperated string[] argC# 重构:解析逗号分隔的字符串 [] arg
【发布时间】:2010-02-09 04:53:13
【问题描述】:

好的,假设有这个:

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

我想用最简单的方法把它变成一个列表。当然,productUidsPostValue 中的字符串需要强类型为Guids,如果它们是有效的Guids。这是我写的代码。当然可以重构或减少,对吧?

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);
      }
}

【问题讨论】:

    标签: c# arrays


    【解决方案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();
    

    【讨论】:

      【解决方案2】:

      你可以这样做:

      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 测试,以节省基于异常的编程,至少比已经做的多一点。

      【讨论】:

      • 对-1有什么解释吗?
      【解决方案3】:

      这是我在不变成不可读代码的情况下能做到的最短时间。 附言。原始代码无法检查 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】:

        你可以使用 LINQ:

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

        【讨论】:

        • 这个被改装有什么原因吗?
        • 考虑输入值“693C850B-2B0B-4429-98F8-AE99E92991A8,F37858BD-22E5-4077-BADD-9AFCDCC92628,这不是一个 Guid 但会导致 Guid.Empty 被添加到列表中"
        • @Travis:我认为添加空 Guid 比添加已添加到列表中的最后一个值更好。此外,如果他列表中的第一个值不是有效的 Guid,他的版本也会添加一个空值。
        【解决方案5】:

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

        如果您找出与 C# 等效的 Ruby 集合,您可以使代码更简洁一些(尽管您需要它,但我省略了 guid 验证部分)

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

        【讨论】:

          【解决方案6】:

          如果您使用的是 .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();
          

          【讨论】:

            【解决方案7】:

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

            如果您在这里花费太多精力来安全地处理错误输入,那么您实际上是在寻找问题。例如,客户端代码可能会提供错误的输入字符串,您可以优雅地将其视为好的输入,但含义不同。

            相反,如果无法解析任何项目,我建议您立即失败,因为来自 guid 解析构造函数的任何异常都无法解析,这样您就可以提出最简洁的代码。

            【讨论】:

              猜你喜欢
              • 2021-11-01
              • 2011-02-20
              • 1970-01-01
              • 1970-01-01
              • 2019-12-04
              • 1970-01-01
              • 1970-01-01
              • 2020-06-12
              • 2015-05-24
              相关资源
              最近更新 更多