【问题标题】:Refactoring foreach loop with several of if-else statements用几个 if-else 语句重构 foreach 循环
【发布时间】:2015-12-14 21:22:41
【问题描述】:

我有这种方法,如果SPListItem 的某个字段是null,我会检查几次,如果是,则为该属性写入默认值。有什么办法可以减少这段代码吗?谢谢

public List<Models.EmployeeInfo> GetEmployeeInfo(SPListItemCollection splic)
{           
    List<Models.EmployeeInfo> listEmployeeInfo = new List<Models.EmployeeInfo>();

    foreach (SPListItem item in splic)
    {               
        var employeeInfo = new Models.EmployeeInfo();

        if (item["EmployeeName"] == null)
        {
            employeeInfo.EmployeeName = "";
        }
        else
        {
            employeeInfo.EmployeeName = item["EmployeeName"].ToString();
        }

        if (item["Position"] == null)
        {
            employeeInfo.Position = "";
        }
        else
        {
            employeeInfo.Position = item["Position"].ToString();
        }

        if (item["Office"] == null)
        {
            employeeInfo.Office = "";
        }
        else
        {
            employeeInfo.Office = item["Office"].ToString();
        }

        if (item["IsPublic"] == null)
        {
            employeeInfo.IsPublic = true;
        }
        else
        {
            employeeInfo.IsPublic = Convert.ToBoolean("IsPublic"); 
        }

        listEmployeeInfo.Add(employeeInfo);
    }

    return listEmployeeInfo;                                           
}

【问题讨论】:

  • 我认为您应该尝试使用CodeReview 服务
  • 最后一个应该是Convert.ToBoolean(item["IsPublic"]) 吗?它不匹配所有其他人
  • SPList 的代码是什么?
  • 如何将这些检查和设置默认值放入您的模型设置器中。在我看来它更干净
  • @HankMooody:如果您确实采用 Reflection 方法(由您接受的答案表示),那么link about Reflection in C# 将很有用。

标签: c#


【解决方案1】:

您可以使用一些反射来设置属性。 然后你可以遍历所有属性名的列表并设置它们。 (这样当一个属性被添加到模型中时,你需要做的就是将它添加到字符串列表中)

public List<Models.EmployeeInfo> GetEmployeeInfo(SPListItemCollection splic)
{
    var listEmployeeInfo = new List<Models.EmployeeInfo>();
    var propertyNames = new List<string>(){"EmployeeName","Position","Office","IsPublic"}

    foreach (SPListItem item in splic)
    {
        var employeeInfo = new Models.EmployeeInfo(); 

        foreach (var propertyName in propertyNames)
        {  
            string newData = "";
            if (item[propertyName] != null)
            {
                newData = item[propertyName];
            }
            employeeInfo.GetType().GetProperty(propertyName).SetValue(employeeInfo, newData, null); 
        }

        listEmployeeInfo.Add(employeeInfo);
    }
    return listEmployeeInfo;
}

【讨论】:

  • 这是一个非常有趣的方法,我想使用它,但是我不熟悉 Reflections ,请解释我应该怎么做,因为我不能使用 GetProperty 扩展方法,错误说我的类不包含 GetProperty 扩展方法的定义。谢谢。
  • 忘记添加 GetType()。你现在不应该再收到这个错误了,我已经改变了我的答案。
  • 我已经弄清楚了,谢谢。现在我在该行遇到了其他错误,“对象引用未设置为对象的实例”
  • 发现错误。谢谢 :D
【解决方案2】:

尝试类似:

public List<Models.EmployeeInfo> GetEmployeeInfo(SPListItemCollection splic)
{

  var listEmployeeInfo = new List<Models.EmployeeInfo>();
  foreach (SPListItem item in splic)
  {               
    var employeeInfo = new Models.EmployeeInfo();

    employeeInfo.EmployeeName = item["EmployeeName"] == null ? "" : item["EmployeeName"].ToString();

    employeeInfo.Position = item["Position"] == null ? "" : item["Position"].ToString();
    employeeInfo.Office = item["Office"] == null ? "" : item["Office"].ToString();

    employeeInfo.IsPublic = item["IsPublic"] == null || Convert.ToBoolean("IsPublic");

    listEmployeeInfo.Add(employeeInfo);
  }

  return listEmployeeInfo;
}

【讨论】:

  • 我认为重点是避免重复,而不仅仅是用三元运算符缩短代码
【解决方案3】:

尝试将通用逻辑重构为函数。

employeeInfo.EmployeeName = ConditionalToString(item, "EmployeeName");
employeeInfo.Position = ConditionalToString(item, "Position");
employeeInfo.Office = ConditionalToString(item, "Office");
employeeInfo.IsPublic = item[attrName] == null ? false : Convert.ToBoolean("IsPublic");

string ConditionalToString(SPListItem item, string attrName)
{
    return (item[attrName] == null ? "" : item[attrName].ToString());
}

null coalesce operator 不起作用,因为 item[attrName] 和 "" 是不同的类型,所以这样的东西不起作用:(item[attrName] ?? "").ToString()dynamic 在这种情况下会有所帮助吗?我没有经常使用)。

TLJ's comment 是这种逻辑发生位置的替代解决方案(尽管您仍然会在那里重复相同)。

【讨论】:

    【解决方案4】:

    我同意这里给出的另一个使用三元运算符的答案。奇怪的是我昨天也在研究同样的东西。您可以并且应该在此处使用三元运算符而不是 if - else

    优势?

    • 一方面,它可以使代码更短,一目了然。
    • 更大的优势是...您当前的代码是基于语句的。所以你正在做的是你正在测试一个条件并执行语句作为该条件的副作用但是当使用三元运算符时,您 使用表达式来计算结果(这正是您想要做的 - 您正在尝试生成要放入的 employeeInfo 对象列表)。
    • 在您当前的设计中,每个属性都有 2 个分配值的位置(if 块和 else 块)。使用三元运算符时,值仅分配在一个位置。

    此外,您可以将employeeInfo 对象创建重构为另一个方法,并保持当前方法更简洁(如下所示):

    public List<Models.EmployeeInfo> GetEmployeeInfo(SPListItemCollection splic)
    {
        var listEmployeeInfo = new List<Models.EmployeeInfo>();
        foreach (SPListItem splicItem in splic)
        {               
          listEmployeeInfo.Add(CreateEmployeeInfoFromItem(splicItem));
        }
        return listEmployeeInfo;
    }
    
    private static Models.EmployeeInfo CreateEmployeeInfoFromItem(SPListItem item)
    {
        var employeeInfo = new Models.EmployeeInfo();
        employeeInfo.EmployeeName = item["EmployeeName"] == null ? "" : item["EmployeeName"].ToString();
        employeeInfo.Position = item["Position"] == null ? "" : item["Position"].ToString();
        employeeInfo.Office = item["Office"] == null ? "" : item["Office"].ToString();
        employeeInfo.IsPublic = item["IsPublic"] == null || Convert.ToBoolean("IsPublic");
        return employeeInfo;
    }
    

    【讨论】:

      【解决方案5】:

      我会考虑创建一个映射对象,该对象仅负责从给定的 SPListItem 实例创建一个 EmployeeInfo 实例。在此映射对象中,您将拥有您的验证标准/设置标准,然后在您有此需求的任何时候,您都有一个很好的映射对象可以完成这项工作。

      public class SPListItemToEmployeeInfoMapper
      {
          public static Models.EmployeeInfo Map(SpListItem item);
          { //your logic here to create the employeeinfo from SpListItem }
      }
      

      那么你的来电者:

      public List<Models.EmployeeInfo> GetEmployeeInfo(SPListItemCollection splic)
      {
         var listEmployeeInfo = new List<Models.EmployeeInfo>();
         foreach (SPListItem splicItem in splic)
         {               
            listEmployeeInfo.Add(SPListItemToEmployeeInfoMapper.Map(splicItem));
         }
         return listEmployeeInfo;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-11
        • 2019-12-12
        • 2012-09-02
        • 1970-01-01
        • 2015-10-28
        • 1970-01-01
        • 2020-03-20
        • 2017-02-17
        相关资源
        最近更新 更多