我有一个foreach循环,需要执行一些逻辑时,最后一项是从列表中选择,例如:

 foreach (Item result in Model.Results)
 {
      //if current result is the last item in Model.Results
      //then do something in the code
 }

我可以知道哪个循环是最后没有使用循环和计数器吗?


当前回答

".Last()"对我不起作用,所以我不得不这样做:

Dictionary<string, string> iterativeDictionary = someOtherDictionary;
var index = 0;
iterativeDictionary.ForEach(kvp => 
    index++ == iterativeDictionary.Count ? 
        /*it's the last item */ :
        /*it's not the last item */
);

其他回答

正如Chris所展示的,Linq可以工作;只需使用Last()来获得枚举对象中最后一个的引用,只要你没有使用该引用,那么就执行正常的代码,但如果你正在使用该引用,那么就执行额外的事情。它的缺点是它总是O(N)-复杂度。

你可以使用Count()(如果IEnumerable也是一个ICollection, Count()是O(1);这对于大多数常见的内置IEnumerables都是正确的),并将foreach与计数器混合:

var i=0;
var count = Model.Results.Count();
foreach (Item result in Model.Results)
{
    if (++i == count) //this is the last item
}

要对除最后一个元素之外的每个元素做一些额外的事情,可以使用基于函数的方法。

delegate void DInner ();

....
    Dinner inner=delegate 
    { 
        inner=delegate 
        { 
            // do something additional
        } 
    }
    foreach (DataGridViewRow dgr in product_list.Rows)
    {
        inner()
        //do something
    }
}

这种方法有明显的缺点:对于更复杂的情况,代码更不清晰。调用委托可能不是很有效。排除故障可能不太容易。好的一面——编码很有趣!

话虽如此,如果你知道你的集合的计数不是特别慢,我建议在一些不重要的情况下使用plain for循环。

迭代器实现没有提供这一点。您的集合可能是一个IList,可以通过O(1)中的索引访问。在这种情况下,你可以使用一个普通的for循环:

for(int i = 0; i < Model.Results.Count; i++)
{
  if(i == Model.Results.Count - 1) doMagic();
}

如果您知道计数,但不能通过索引访问(因此,result是一个ICollection),您可以通过在foreach的主体中增加i并将其与长度进行比较来进行计数。

所有这些都不是完美的优雅。克里斯的解决方案可能是我迄今为止见过的最好的。

如果你只需要对最后一个元素做一些事情(而不是对最后一个元素做一些不同的事情),那么在这里使用LINQ会有所帮助:

Item last = Model.Results.Last();
// do something with last

如果你需要对最后一个元素做一些不同的事情,那么你需要这样的东西:

Item last = Model.Results.Last();
foreach (Item result in Model.Results)
{
    // do something with each item
    if (result.Equals(last))
    {
        // do something different with the last item
    }
    else
    {
        // do something different with every item but the last
    }
}

不过,您可能需要编写一个自定义比较器,以确保您可以判断该项与Last()返回的项相同。

这种方法应该谨慎使用,因为Last可能必须遍历集合。虽然这对于小型集合可能不是问题,但如果它变得很大,可能会对性能产生影响。如果列表包含重复的项,也会失败。在这种情况下,这样的语句可能更合适:

int totalCount = result.Count();
for (int count = 0; count < totalCount; count++)
{
    Item result = Model.Results[count];

    // do something with each item
    if ((count + 1) == totalCount)
    {
        // do something different with the last item
    }
    else
    {
        // do something different with every item but the last
    }
}
     List<int> ListInt = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };


                int count = ListInt.Count;
                int index = 1;
                foreach (var item in ListInt)
                {
                    if (index != count)
                    {
                        Console.WriteLine("do something at index number  " + index);
                    }
                    else
                    {
                        Console.WriteLine("Foreach loop, this is the last iteration of the loop " + index);
                    }
                    index++;

                }
 //OR
                int count = ListInt.Count;
                int index = 1;
                foreach (var item in ListInt)
                {
                    if (index < count)
                    {
                        Console.WriteLine("do something at index number  " + index);
                    }
                    else
                    {
                        Console.WriteLine("Foreach loop, this is the last iteration of the loop " + index);
                    }
                    index++;

                }