C# 用LINQ表达式替换foreach

C# 用LINQ表达式替换foreach,c#,linq,C#,Linq,我有这样一个代码: foreach (var optionValues in productOption.ProductOptionValues) { if (optionValues.ProductOptionValueID > 0) { unitOfWork.ProductContext.Entry(optionValues).State = EntityState.Modified; } else { unitOfWork.ProductConte

我有这样一个代码:

foreach (var optionValues in productOption.ProductOptionValues)
{
  if (optionValues.ProductOptionValueID > 0)
  {
    unitOfWork.ProductContext.Entry(optionValues).State = EntityState.Modified;
  }
  else
  {
    unitOfWork.ProductContext.Entry(optionValues).State = EntityState.Added;
  }
}
productOption.ProductOptionValues.ForEach(x => 
   unitOfWork.ProductContext.Entry(x).State = (
      (x.ProductOptionValueID > 0) ? EntityState.Modified : EntityState.Added)
)
对此的代码审查是,我应该考虑使用LINQ来实现这一点


有人能告诉我一个资源,可以解释使用LINQ来更改对象属性吗?

LINQ用于查询。您正在修改值,因此,
foreach
在这里非常好。

您没有。就这么简单

对此的代码审查是,我应该考虑使用LINQ来实现这一点,并避免使用foreach


告诉代码审阅者他错了。LinQ用于Q查询数据。您正在更新数据。继续使用foreach循环,这很好。

这里LINQ的唯一合理使用(取决于
ProductOptionValues
的类型)是使用过滤结果,这基本上取代了
if
语句,但并不比您当前的代码好:

foreach (var option in productOption.ProductOptionValues.Where(x => x.ProductOptionValueID > 0)
    unitOfWork.ProductContext.Entry(optionValues).State = EntityState.Modified;

foreach (var option in productOption.ProductOptionValues.Where(x => x.ProductOptionValueID <= 0)
    unitOfWork.ProductContext.Entry(optionValues).State = EntityState.Added;
foreach(productOption.ProductOptionValues.Where中的var选项(x=>x.ProductOptionValueID>0)
unitOfWork.ProductContext.Entry(optionValues).State=EntityState.Modified;

foreach(productOption.ProductOptionValues.Where(x=>x.ProductOptionValueID中的var选项)您能做的最好的事情是:

var query =
    from optionValues in productOption.ProductOptionValues
    select new
    {
        entry = unitOfWork.ProductContext.Entry(optionValues),
        value = optionValues.ProductOptionValueID > 0
            ? EntityState.Modified
            : EntityState.Added
    };

foreach (var x in query)
{
    x.entry.State = x.value;
}

但我认为这在可读性方面并没有给你太多帮助。

假设productOption.ProductOptionValues是一个IList()(如果不是,你可能需要在.ForEach之前先做一个.ToList()),它会是这样的:

foreach (var optionValues in productOption.ProductOptionValues)
{
  if (optionValues.ProductOptionValueID > 0)
  {
    unitOfWork.ProductContext.Entry(optionValues).State = EntityState.Modified;
  }
  else
  {
    unitOfWork.ProductContext.Entry(optionValues).State = EntityState.Added;
  }
}
productOption.ProductOptionValues.ForEach(x => 
   unitOfWork.ProductContext.Entry(x).State = (
      (x.ProductOptionValueID > 0) ? EntityState.Modified : EntityState.Added)
)
…但我不认为这真的是一种进步。事实上恰恰相反


真的,不要这样做。

很棘手,只是为了幽默,有几种可能的方式,例如:

var sum = productOption.ProductOptionValues.Select(
         optionValues => unitOfWork.ProductContext.Entry(optionValues).State = (optionValues.ProductOptionValueID > 0 ? EntityState.Modified : EntityState.Added).Sum();

您不应该使用LINQ ForEach扩展。让我解释一下原因:

LINQforeach违反了所有其他序列操作符所基于的函数编程原则。 显然,调用此方法的唯一目的是产生副作用。表达式的目的是计算值,而不是产生副作用。 声明的目的是产生副作用。这个东西的调用站点看起来非常像一个表达式

第二个原因是,使用它会为代码添加零表示值。这样做可以让您重写这段非常清晰的代码:

foreach(Foo-Foo-in-foos){涉及Foo的语句;}

在此代码中:

ForEach((Foo-Foo)=>{涉及Foo的语句;})

第二个版本更难理解,更难调试,并且引入了闭包语义,从而以微妙的方式潜在地改变了对象的生命周期

以上是Eric Lippert的一篇博文的部分摘要。请阅读全文

此外,BCL团队已在Windows 8中删除该扩展:

Metro风格的应用程序中已经删除了List.ForEach。虽然该方法看起来很简单,但当传递给ForEach的方法改变列表时,可能会出现一些潜在问题


相反,建议您只使用foreach循环。

为什么要使用linq isntead替代foreach?为什么要避免使用foreach?我想看看在这里使用linq的理由。linq是一种查询语法,因此在您的环境中并不真正适合。不过,这里有一个简单的扩展,您可以使用它。也许避免是错误的word。编辑了问题。您可能想要使用的内容,但您的原始代码仍然很好。严格来说,这甚至不是LinQ,因为
ForEach
List
的方法,而不是
System.LinQ
的扩展方法。