【问题标题】:ToList().ForEach in LinqLinq 中的 ToList().ForEach
【发布时间】:2011-10-19 05:08:26
【问题描述】:

我是 Linq 的新手。

我想像这样在foreach 语句中设置两个值

我的实际代码是这样的

foreach (Employee emp in employees)
{
    foreach(Department dept in emp.Departments)
    {
        dept.SomeProperty = null;
    }
    collection.AddRange(emp.Departments);              
}

一点点重构就可以把上面变成这个

foreach (Employee emp in employees)
{
    emp.Departments.ToList().ForEach(u => u.SomeProperty = null))
    collection.AddRange(emp.Departments);              
}

但我想要这样的东西

employees.ToList().Foreach(collection.AddRange(emp.Departments),
emp.Departments.ToList().ForEach(u => u.SomeProperty = null))
  

【问题讨论】:

  • 不!不要将您的集合转换为列表只是为了调用该方法...使用您的循环。
  • 改用 Linq 时也要考虑性能。与普通循环相比,LINQ 并不总是有用。
  • 这样做,没有人可以再次阅读您的代码。自我混淆。
  • 原代码清晰易懂;我看没必要改。请记住,代码的目的不仅仅是与 编译器 交流,而是与代码的未来读者交流;尽可能清楚。
  • @EricLippert 谢谢埃里克。如果我现在不习惯阅读所有 cmets,我会错过这个宝贵的建议。

标签: c# linq entity-framework


【解决方案1】:

您不应该以这种方式使用ForEach。阅读 Lippert 的“foreach” vs “ForEach”

如果你想对自己(和世界)残忍,至少不要创造无用的List

employees.All(p => {
    collection.AddRange(p.Departments);
    p.Departments.All(u => { u.SomeProperty = null; return true; } );
    return true;
});

请注意,All 表达式的结果是我们丢弃的 bool 值(我们使用它只是因为它“循环”所有元素)

我再重复一遍。您不应该使用ForEach 来更改对象。 LINQ 应该以“功能”方式使用(您可以创建新对象,但不能更改旧对象,也不能创建副作用)。而你正在写的是创建这么多无用的List 只是为了获得两行代码......

【讨论】:

  • 虽然我们在这里建议的是用 All 滥用替换 ToList() 滥用。 ;)
  • @IlianPinzon 我以为我很清楚这一点。你认为我应该加粗吗? :-)
  • 我更喜欢闪烁的字幕,上面写着“请勿(AB)使用”。 :) 如果新手跳过上面的免责声明文本,他们可能会将此示例视为福音。 :)
  • 至少在删除 ToList 后,它不会将集合复制到内存中,只是为了对其进行迭代并将其丢弃。在大型集合上 ToList 是致命的。
【解决方案2】:

正如 xanatos 所说,这是对 ForEach 的滥用。

如果你打算使用 linq 来处理这个问题,我会这样做:

var departments = employees.SelectMany(x => x.Departments);
foreach (var item in departments)
{
    item.SomeProperty = null;
}
collection.AddRange(departments);

但是,循环方法更具可读性,因此更易于维护。

【讨论】:

  • +1 哇!漂亮地使用SelectMany(不是我会使用它:-))
  • 尽管在修改范围后添加范围可能会更好,因此从逻辑上讲,您将修改后的项目添加到集合中是有意义的。该集合甚至可以存储项目的副本,因此这可能不起作用。
  • 删除AddRange 行可能会更好,因为它会对序列进行不必要的额外遍历。可以在现有循环中执行collection.Add(item) 并获得相同的结果。
  • @Jeff 我没想到,修好了。
【解决方案3】:
employees.ToList().ForEach(
     emp=>
     {
          collection.AddRange(emp.Departments);
          emp.Departments.ToList().ForEach(u=>u.SomeProperty = null);
     });

【讨论】:

  • 所以添加 .ToList() 允许 Linq .ForEach()... 很好!
【解决方案4】:

试试这个:

foreach (var dept in employees.SelectMany(e => e.Departments))
{
   dept.SomeProperty = null;
   collection.Add(dept);
}

【讨论】:

    【解决方案5】:
    employees.ToList().Foreach(u=> { u.SomeProperty = null; u.OtherProperty = null; });
    

    请注意,我在每个 set 语句后都使用了分号 那就是 -->

    u.SomeProperty = null;
    u.OtherProperty = null;
    

    我希望这一定能解决您的问题。

    【讨论】:

      【解决方案6】:

      您可以使用Array.ForEach()

      Array.ForEach(employees, employee => {
         Array.ForEach(employee.Departments, department => department.SomeProperty = null);
         Collection.AddRange(employee.Departments);
      });
      

      【讨论】:

        【解决方案7】:

        你想要这个吗?

            employees.ForEach(emp =>
            {
                collection.AddRange(emp.Departments.Where(dept => { dept.SomeProperty = null; return true; }));
            });
        

        【讨论】:

          【解决方案8】:

          试试这个 Lambda 表达式的组合:

          employees.ToList().ForEach(emp => 
          {
              collection.AddRange(emp.Departments);
              emp.Departments.ToList().ForEach(dept => dept.SomeProperty = null);                    
          });
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-05-25
            • 1970-01-01
            相关资源
            最近更新 更多