2016-09-02 4 views
3

Я пытаюсь использовать метод IEnumerable внутри a для каждого цикла, но я не могу заставить его работать исправно.Ienumerable concat не работает для каждого цикла

IEnumerable<Geo> geos = null; 
foreach (string a in values) 
{ 
    if (geos == null) 
     geos = entities.Geos.Where(g => (g.ACode == Convert.ToInt16(a))); 
    else 
     geos = geos.Concat(entities.Geos.Where(g => (g.ACode == Convert.ToInt16(a)))); 
} 

Что он возвращает только значения окончательный «а» в значениях, которые тоже для подсчета записей, присутствующих в значениях.

Так что, если у меня есть 1,2,3 в качестве значений, он возвращается только для 3. Мне также нужно значение для 1,2 и 3.

Куда я иду не так?

+1

Я бы проверил, что 'entities.Geos.Where (g => (g.ACode == Convert.ToInt16 (a)))' фактически возвращает строки для 1 и 2. Также, какая версия Visual Studio вы используя, beahvior переменных захватов в цикле foreach, измененных в 2013 году –

+1

@Scott Chamberlain возвращает значения как для 1, так и для 2, я использую VS 2010 –

ответ

6

Вполне вероятно, вы используете старую версию C#, в C# 5 (поставляется с Visual Studio 2013), они изменили поведение foreach. В C# 4 a в g => (g.ACode == Convert.ToInt16(a)) будет последним значением foreach при оценке lazely, в C# 5 и новее оно всегда будет текущим значением.

Чтобы получить поведение C# 5, вам просто нужно объявить дополнительную переменную внутри области цикла foreach и использовать ее в захвате.

IEnumerable<Geo> geos = null; 
foreach (string a in values) 
{ 
    string b = a; 
    if (geos == null) 
     geos = entities.Geos.Where(g => (g.ACode == Convert.ToInt16(b))); 
    else 
     geos = geos.Concat(entities.Geos.Where(g => (g.ACode == Convert.ToInt16(b)))); 
} 

Если вам интересно вещь, что изменилось в C# 4 и ниже исходного кода переводится, чтобы

IEnumerable<Geo> geos = null; 
using(IEnumerator<string> enumerator = values.GetEnumerator()) 
{ 
    string a; 
    while(enumerator.MoveNext()) 
    { 
     a = enumerator.Current; 

     if (geos == null) 
      geos = entities.Geos.Where(g => (g.ACode == Convert.ToInt16(a))); 
     else 
      geos = geos.Concat(entities.Geos.Where(g => (g.ACode == Convert.ToInt16(a)))); 
    } 
} 

В C# 5 и более поздние версии он переводится на

IEnumerable<Geo> geos = null; 
using(IEnumerator<string> enumerator = values.GetEnumerator()) 
{ 
    while(enumerator.MoveNext()) 
    { 
     string a = enumerator.Current; 

     if (geos == null) 
      geos = entities.Geos.Where(g => (g.ACode == Convert.ToInt16(a))); 
     else 
      geos = geos.Concat(entities.Geos.Where(g => (g.ACode == Convert.ToInt16(a)))); 
    } 
} 

Выполняя string b = a; в C# 4, мы воссоздаем это поведение декларации, находящейся внутри while петля.

+0

Спасибо Скотту, добавив, что эта линия работает. –

+0

Большое спасибо @Scott за подробное объяснение, это то, что я узнал сегодня. –

1

Из того, что я понимаю, что вы хотите сделать, есть все Geos, что ACode. Вместо того, чтобы идти по списку Geos для каждого a вы можете сделать это следующим образом:

var intValues = values.Select(value => Convert.ToInt16(value)); 
var geos = entities.Geos.Where(g => intValues.Contains(g.ACode)); 
Смежные вопросы