2009-11-29 14 views
7

ForEach'ta bir lambda ifadesinde koşullu bir operatöre izin verilmiyor mu?Koşullu operatörü lambda ifadesinde, genel bir Listede ForEach() içinde kullanma?

List<string> items = new List<string>{"Item 1", "Item 2", "Item I Care About"}; 

string whatICareAbout = ""; 

// doesn't compile :(
items.ForEach(item => item.Contains("I Care About") ? 
whatICareAbout += item + "," : whatICareAbout += ""); 

Derleme hatası -> da işe yaramazsa normal kullanmaya çalışıyor

"Yalnızca atama, çağrı Artırma, azaltma ve yeni nesne ifadeleri açıklamada olarak kullanılabilir":

// :(
items.ForEach(item => if (item.Contains("I Care About")) {whatICareAbout += item + ", ";} 

Sadece olanaklı değil misiniz?

+2

Sheesh Yanıtlarımdan çok etkilendim, hepsi birkaç dakika içinde soruyorum :) Sanırım @SLaks sorumu yanıtlıyor, ama Agrega() aklımı uçuruyor! :) Tekrar herkese teşekkürler :) – Jamezor

+1

Bir koşullu işleç türü olarak bir dize ifadesi vardı ve .ForEach() yönteminiz için bir ifade gerekiyordu. Bu yüzden derleme hatası vardı. –

+1

@Roman - Şimdi anladım! Bence bir? x: y (a) {x} else {y} için kısa el olarak değil ama? Bu durumda bir dize olan x ve y değerini döndürür ... – Jamezor

cevap

26

Yalnızca tek bir ifadeye izin veren daha kısa biçimdeki lambda ifadelerini kullanıyorsunuz.
Çok sayıda ifadeye izin veren uzun forma ihtiyacınız var. Örneğin

:

items.ForEach(item => { 
    if (item.Contains("I Care About")) 
     whatICareAbout += item + ", "; 
}); 
1

deneyin parantez:

items.ForEach(item => item.Contains("I Care About") ? (whatICareAbout += item + ",") : (whatICareAbout += "")); 

+ = Eğer hata alıyorsanız neden olabilmektedir daha yüksek önceliğe sahiptir?. Parantez ile hata gider. Bununla ilgili% 100 emin değilim, ancak ... lambda ifadeleri, atama bildirimlerinin kullanılmasını engelleyen ek kısıtlamalara sahip olabilir.

GÜNCELLEME: Böyle olduğu için sağ taraftaki koşullu koymak

yerine çoklu + = tabloların

, bu çok daha temiz:

List<string> items = new List<string> { "one", "two", "three" }; 
string whatICareAbout = ""; 
items.ForEach(item => whatICareAbout += item.Contains("I Care About") ? (item + ",") : ""); 

GÜNCELLEME 2:

Ancak, bu senaryo için tasarlandığından Aggregate() yöntemini kullanmanız daha da iyidir.

string whatICareAbout = items.Aggregate("", (total, item) => item.Contains("I Care About") ? (total + item + ",") : total); 

Ama (ben bu göndermek üzereyken ben sadece gördüm) o terminali çıkarmadan ile ilgilenen beri benim örnek daha iyidir "" @Matt Breckon's yanıt yukarıda düşünüyorum: İşte bir örnek. Onun cevabına bak ... :-)

5

Neyi zahmet etmeye çalışıyorsun? Belirli bir değeri içerdikleri bir virgülle ayrılmış öğeler dizesi oluşturmaya mı çalışıyorsunuz? linq olarak aşağıdaki kullanarak bunu başarmak olacaktır: bundan

List<string> items = new List<string> { "Item 1", "Item 2", "Item I Care About", "Item I Care About", "Item I Care About" }; 
string whatICareAbout = items.Where(x => x.Contains("I Care About")) 
           .Aggregate((y, z) => y + ", " + z); 

çıkışı "Ben hakkında Bakımı Ürün, ben hakkında Bakımı Ürün, Ürün ı hakkında Bakımı".

Not: Agrega "" Sonuna yoktur sağlamanın harika bir yoludur

+0

Sting concat için 'Agrega'yı kullanmak düşünmediğim çok güzel bir fikir. 'StringBuilder' akıcı bir arayüze sahip olduğundan bir' StringBuilder' kullanmak için kolayca değiştirebilirsiniz. – SLaks

+0

hah, ilk yanıtıma bir Aggregate() kod örneği ekliyordum ... ama ben seninkini daha çok seviyorum. +1! –

4

sorun ifadesi

item.Contains("I Care About") ? whatICareAbout += item + "," : whatICareAbout += "" 

bir açıklama olmadığını oldu. Sadece string türüne sahip bir değer döndürür.

Orada o (sadece eğlence için) çalışmasını sağlamak için bir hile: İlk ifadeden bir açıklama oluşturmak için .GetType() yönteme

items.ForEach(item => (item.Contains("I Care About") ? 
    whatICareAbout += item + "," : whatICareAbout += "").GetType()); 

Sadece eklendi çağrı ve derlenmiş.

+0

Ve '.ForEach() için bir ifadeye ihtiyacın var :) –

İlgili konular