关于C#:IEnumerable concat不适用于每个循环

Ienumerable concat not working in for each loop

本问题已经有最佳答案,请猛点这里访问。

我试图在for each循环中使用IEnumerable的Concat方法,但是我不能使它正常工作。

1
2
3
4
5
6
7
8
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))));
}

它返回的只是值中最后一个"a"的值,也就是值中存在的记录的计数。

所以如果我有1,2,3作为值,它只返回3。我还需要1、2和3的值。

我哪里出错了?


很可能您使用的是C的旧版本,在C 5(与Visual Studio 2013一起提供)中,它们改变了foreach的行为。在c 4中,g => (g.ACode == Convert.ToInt16(a))中的a将是foreach的最后一个值,在c 5及更高版本中,它将始终是当前值。

要获得C 5行为,只需在foreach循环的范围内声明一个额外的变量,并在捕获中使用它。

1
2
3
4
5
6
7
8
9
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中,并且低于原来的代码会被翻译成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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和更新版本中,它被转换为

1
2
3
4
5
6
7
8
9
10
11
12
13
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))));
    }
}

通过在C 4中执行string b = a;,我们重新创建了声明在while循环中的行为。


据我所知,你想做的是让所有的Geos都和ACode一样。您可以这样做,而不必为每个a检查Geos的列表:

1
2
var intValues = values.Select(value => Convert.ToInt16(value));
var geos = entities.Geos.Where(g => intValues.Contains(g.ACode));