簡體   English   中英

用LINQ表達式替換foreach

[英]Replacing a foreach with LINQ expression

所以我有這樣的代碼:

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

為此的代碼審查是,我應該考慮使用LINQ來做到這一點。

有人可以給我指出可以使用LINQ更改對象屬性的資源嗎?

你不知道 就那么簡單。

為此的代碼回顧是,我應該考慮使用LINQ來做到這一點,並避免使用foreach。

告訴代碼檢查者他錯了。 Q是對於Q uerying數據。 您正在更新數據。 保持foreach循環的正常。

LINQ用於查詢。 您正在修改值,因此foreach在這里很好。

您能做的最好的事情是:

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

但是我不認為這在可讀性方面確實給您帶來很多好處。

LINQ的唯一合理用法(並取決於ProductOptionValues的類型)是使用Where過濾結果, Where本質上替代了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;

您不應該使用LINQ ForEach擴展。 讓我解釋一下原因:

LINQ foreach違反了所有其他序列運算符所基於的功能編程原理。 顯然,調用此方法的唯一目的是引起副作用。 表達式的目的是計算一個值,而不引起副作用。 聲明的目的是引起副作用。 這個東西的呼叫站點看起來很像一個表情

第二個原因是使用它會為您的代碼添加零表示值。 這樣做使您可以重寫以下完全清晰的代碼:

foreach(foos中的Foo foo){涉及foo的語句; }

變成這段代碼:

foos.ForEach((Foo foo)=> {涉及foo;的語句);

它使用幾乎完全相同的字符,但順序略有不同。 但是第二個版本更難理解,更難調試,並且引入了閉包語義,從而有可能以微妙的方式改變對象的生存期。

上面部分是Eric Lippert的博客文章的摘要。 此處閱讀全文。

此外,Windows 8中的BCL團隊已刪除了該擴展:

List.ForEach已在Metro風格應用中刪除。 盡管該方法看起來很簡單,但是當列表通過傳遞給ForEach的方法進行變異時,它存在許多潛在的問題。

相反,建議您僅使用一個foreach循環。

假設productOption.ProductOptionValues是一個IList <>()(如果不是,則可能需要在.ForEach之前執行.ToList()),如下所示:

productOption.ProductOptionValues.ForEach(x => 
   unitOfWork.ProductContext.Entry(x).State = (
      (x.ProductOptionValueID > 0) ? EntityState.Modified : EntityState.Added)
)

...但是我認為這並不是真正的進步。 實際上,恰恰相反。

真的,不要這樣做。

整rick,僅出於幽默,它可以通過多種方式實現,例如:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM