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

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

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


当前回答

     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++;

                }

其他回答

你可以创建一个专门用于此的扩展方法:

public static class EnumerableExtensions {
    public static bool IsLast<T>(this List<T> items, T item)
        {
            if (items.Count == 0)
                return false;
            T last = items[items.Count - 1];
            return item.Equals(last);
        }
    }

你可以这样使用它:

foreach (Item result in Model.Results)
{
    if(Model.Results.IsLast(result))
    {
        //do something in the code
    }
}

另一种方法是使用Queue(队列),我没有看到它被贴出来。这类似于实现SkipLast()方法而无需进行不必要的迭代。这种方法也可以让你在任何数量的最后一项上这样做。

public static void ForEachAndKnowIfLast<T>(
    this IEnumerable<T> source,
    Action<T, bool> a,
    int numLastItems = 1)
{
    int bufferMax = numLastItems + 1;
    var buffer = new Queue<T>(bufferMax);
    foreach (T x in source)
    {
        buffer.Enqueue(x);
        if (buffer.Count < bufferMax)
            continue; //Until the buffer is full, just add to it.
        a(buffer.Dequeue(), false);
    }
    foreach (T item in buffer)
        a(item, true);
}

要调用它,你需要执行以下操作:

Model.Results.ForEachAndKnowIfLast(
    (result, isLast) =>
    {
        //your logic goes here, using isLast to do things differently for last item(s).
    });

如果你只需要对最后一个元素做一些事情(而不是对最后一个元素做一些不同的事情),那么在这里使用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
    }
}

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

delegate void DInner ();

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

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

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

var last = objList.LastOrDefault();
foreach (var item in objList)
{
  if (item.Equals(last))
  {
  
  }
}