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
的扩展方法。