2008-11-17 13 views
15

Birkaç anahtar kelime içeren bir Listem var. Öyle (kod gürültüyü kaldırmak için aşağı haşlanmış) gibi onlarla benim linq sorgusu bina içlerinden foreach: ben artık tuşları seperatly sonuç 2 anahtarlar içeren yaptığınızdaForeach döngüsünde yerleşik olan Linq sorgusu her zaman son yinelemeden parametre değeri alır

List<string> keys = FillKeys() 
foreach (string key in keys){ 
    q = q.Where(c => c.Company.Name.Contains(key)); 
} 

, ancak birlikte occure asla (q içindeki her öğe ya "xyz" ya da "123", asla "123" ve "xyz"), hala sonuç alırım. Sonuçlar daha sonra alması gereken son dize ile aynıdır.

Linq sorgusuna baktım ve doğru sql oluşturduğunu görüyor, ancak aynı (son yinelenen) değer tarafından @ p1 AND @ p2'nin yerini alıyor.

Neyi yanlış yapıyorum?

+0

olası yinelenen http://stackoverflow.com/questions/271440/c-sharp-captured- döngü için ilgilendirmez değişken döngüde) – nawfal

cevap

31

Aynı değişken (key) lambda ifadenizde yeniden kullanıyorsunuz.

fazla ayrıntı için anonymous methods benim makalesine bakın ve sorular SO ilgili bir dizi çok vardır:

basit bir düzeltme ilk değişkeni kopyalamak için: Muhtemelen yakalanan değişken bir konu

List<string> keys = FillKeys() 
foreach (string key in keys){ 
    string copy = key; 
    q = q.Where(c => c.Company.Name.Contains(copy)); 
} 
+0

Hehe, bunu şu anda buldu: http://stackoverflow.com/questions/190227/building-a-linq-query-programatically-without-local-variables-tricking-me Kolay (ama kazanılan) kredileri size;) –

+0

beni tekrar yolladı ... –

12

; eklemeyi deneyin:

List<string> keys = FillKeys() 
foreach (string key in keys){ 
    string tmp = key; 
    q = q.Where(c => c.Company.Name.Contains(tmp)); 
} 
+0

Teşekkürler. Temel olarak skeet ile aynı şey, ama sadece bir çözüm atayabilirim. Puanlar olsa da. –

+1

Sorun değil. Aynı cevabı verdiğimize güveniyorum; –

1

o C# 5.0 sabit ve yukarıdaki örnekte C# 5.0 eserlerinde ama C# önceki sürümlerinde başarısız oldu.

Ama dikkatli olun, bu

static void Main() 
     { 
      IEnumerable<char> query = "aaa bbb ccc"; 
      string lettersToRemove = "ab"; 

      Console.WriteLine("\nOK with foreach:"); 
      foreach (var item in lettersToRemove) 
      { 
       query = query.Where(c => c != item); 
      } 
      foreach (char c in query) Console.Write(c); 

      //OK: 
      Console.WriteLine("\nOK with foreach and local temp variable:"); 
      query = "aaa bbb ccc"; 

      foreach (var item in lettersToRemove) 
      { 
       var tmp = item; 
       query = query.Where(c => c != tmp); 
      }    
      foreach (char c in query) Console.Write(c); 


      /* 
      An IndexOutOfRangeException is thrown because: 
      firstly compiler iterates the for loop treating i as an outsite declared variable 
      when the query is finnaly invoked the same variable of i is captured (lettersToRemove[i] equals 3) which generates IndexOutOfRangeException 

      The following program writes aaa ccc instead of writing ccc: 
      Each iteration gets the same variable="C", i (last one frome abc). 
      */ 

      //Console.WriteLine("\nNOK with for loop and without temp variable:"); 
      //query = "aaa bbb ccc"; 

      //for (int i = 0; i < lettersToRemove.Length; i++) 
      //{ 
      // query = query.Where(c => c != lettersToRemove[i]); 
      //} 
      //foreach (char c in query) Console.Write(c); 

      /* 
      OK 
      The solution is to assign the iteration variable to a local variable scoped inside the loop 
      This causes the closure to capture a different variable on each iteration. 
      */ 
      Console.WriteLine("\nOK with for loop and with temp variable:"); 
      query = "aaa bbb ccc"; 

      for (int i = 0; i < lettersToRemove.Length; i++) 
      { 
       var tmp = lettersToRemove[i]; 
       query = query.Where(c => c != tmp); 
      } 
      foreach (char c in query) Console.Write(c); 
     } 
[Çevrimde C# Yakalanan Değişken] (içinde
İlgili konular