2017-05-05 176 views
0

我遇到了一個問題,我想返回匹配結果的地方,如果我試圖匹配的其中一個屬性爲空,我會得到一個錯誤。linq空值where子句

if (!string.IsNullOrEmpty(searchString)) 
    { 
     Infos = Infos.Where(
      x => 
      x.FirstName.ToLower().Contains(searchString) || 
      x.LastName.ToLower().Contains(searchString) || 
      x.ContractNum.ToLower().Contains(searchString) || 
      x.VIN.ToLower().Contains(searchString) || 
      x.Claim.InitiatedBy.ToLower().Contains(searchString) 
     ).ToList(); 
    } 

如果ContractNumVIN,例如,是空值,則它會引發錯誤。我不知道如何檢查它們中的一個在linq查詢中是否爲null。

+1

LINQ表達式與常規布爾表達式沒有區別,因此檢查null是一樣的。 –

回答

1

檢查屬性是比較它,它是我知道

if (!string.IsNullOrEmpty(searchString)) 
     { 
      Infos = Infos.Where(
       x => 
       (!String.IsNullOrEmpty(x.FirstName) && x.FirstName.ToLowerInvariant().Contains(searchString)) || 
       (!String.IsNullOrEmpty(x.LastName) && x.LastName.ToLowerInvariant().Contains(searchString)) || 
       (!String.IsNullOrEmpty(x.ContractNum) && x.ContractNum.ToLowerInvariant().Contains(searchString)) || 
       (!String.IsNullOrEmpty(x.VIN) && x.VIN.ToLowerInvariant().Contains(searchString)) || 
       (x.Claim != null && !String.IsNullOrEmpty(x.Claim.InitiatedBy) && x.Claim.InitiatedBy.ToLowerInvariant().Contains(searchString)) 
      ).ToList(); 
     } 

EXTRA的唯一途徑之前null或空:我添加的Claim財產進行檢查,以確保它看起來不是空的InitiatedBy

額外2:使用內建函數IsNullOrEmpty來比較str編號爲""null所以代碼更清晰。

額外3:使用ToLowerInvarianthttps://msdn.microsoft.com/en-us/library/system.string.tolowerinvariant(v=vs.110).aspx)所以無論文化如何,降低行動都會發揮相同的作用。

+0

我喜歡這個答案最好的完整性,甚至儘管我並不真正關心文化。 Reshaper建議您將最後兩個順序檢查合併到:'(!string.IsNullOrEmpty(x.Claim?.InitiatedBy)&& x.Claim.InitiatedBy.ToLowerInvariant()。Contains(searchString))' –

+1

I同意全能Resharper對此。 – Muffun

+0

我可能會提取一個方法,以避免重複調用'string.IsNullOrEmpty()'和'.ToLowerInvariant()。Contains()'以覆蓋測試條件發生變化的情況。根據域,甚至可以選擇使對象本身公開所述方法(如果適當的話)以進一步減少可能的重複。 –

5

您可以添加明確的null檢查:

Infos = Infos.Where(
     x => 
     (x.FirstName != null && x.FirstName.ToLower().Contains(searchString)) || 
     (x.LastName != null && x.LastName.ToLower().Contains(searchString)) || 
     (x.ContractNum != null && x.ContractNum.ToLower().Contains(searchString)) || 
     (x.VIN != null   && x.VIN.ToLower().Contains(searchString)) || 
     (x.Claim != null  && x.Claim.InitiatedBy != null && x.Claim.InitiatedBy.ToLower().Contains(searchString)) 
    ).ToList(); 
+0

你可以嘗試這樣的事情。它將允許null和非null。 (string.Equals(x.ContractNum,string。空)|| x.ContractNum.Trim()。Contains(「searchString」)) –

+0

@JeanB當然,有幾種不同的方法來解決它。隨意添加一個不同的答案。 –

+0

我的想法最近真的被高估了,我不確定爲什麼我沒有這樣做/記住如何做到這一點。我一直試圖放?所有的地方,它不斷給我錯誤。這樣一個簡單的修復。 –

1

你可以使用??與可接受值來代替它。

(x.ContractNum??"").ToLower() 
+2

請不要。不要這樣做。只要定期進行空檢查。 –

+1

區別是什麼? – ThatChris

+1

無用'ToLower()'和後續調用。 –

1

我會用空條件運算?,但是這會,返回null的bool?所以你需要適當地處理這個問題。

如何做到這一點的一些例子:

x?.FirstName?.ToLower().Contains(searchString) == true; 
x?.FirstName?.ToLower().Contains(searchString) ?? false; 
+1

最後的選擇是最好的恕我直言。 –

+0

這隻適用於C#6+。但是,這也是一個不錯的選擇:) –

+2

@PatrickHofman我通常更喜歡最後一個=='真正'和相當於我讀錯了。 – TheLethalCoder

2

你有多種選擇,首先是做對空和其他選項直接檢查是使用空傳播運營商。

x.FirstName != null && x.FirstName.ToLower().Contains(searchString) 

x.FirstName?.ToLower()?.Contains(searchString) == true 

但我建議你使用代替IndexOfContains的情況下 大小寫的比較。

類似:

x.FirstName?.IndexOf(searchString, StringComparison.CurrentCultureIgnoreCase) > 0) 
+0

@TimSchmelter,謝謝蒂姆。 – Habib

+0

建議使用IndexOf的好處是什麼? –

+0

@BarryFranklin,http://haacked.com/archive/2012/07/05/turkish-i-problem-and-why-you-should-care.aspx/ – Habib

1

的另一種方法,以保持比較邏輯在一個地方使用屬性的子集,並檢查這些:

Infos = Infos.Where(i=> 
    new[] {i.FirstName,i.LastName,i.ContractNum /*etc*/} 
    .Any(w=> w?.ToLower().Contains(searchString) ?? false)) 
    .ToList(); 

(它不會讀出所有屬性,但不應該花費不多性能和獲得很大的可維護性)

+0

構建一個新的數組毫無意義,在我看來,可讀性會下降,可能需要更長的時間。我相信它應該是'選擇'而不是'Where'。 – TheLethalCoder

+0

@TheLethalCoder可讀性可能是有爭議的,但不是重複每個獨立屬性的邏輯,而是將它保留在一個地方。 Imho增加了可讀性。 (並且確保人們不能忘記一個屬性的「?」)無論如何,Where是正確的:該陣列僅用於使用它的Any以及匹配時的短路 –

+0

關於性能:是,這在更大的列表中以毫秒爲單位更重,但是如果這是一個問題,我會創建某種迭代器,並將檢查邏輯保存在一個地方 –