Foreach loop, tentukan mana yang merupakan iterasi terakhir dari loop


233

Saya memiliki foreachloop dan perlu menjalankan beberapa logika ketika item terakhir dipilih dari List, misalnya:

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

Bisakah saya tahu loop mana yang terakhir tanpa menggunakan loop dan counter?


1
Lihatlah jawaban saya di sini untuk solusi yang saya posting ke pertanyaan terkait.
Brian Gideon

Jawaban:


294

Jika Anda hanya perlu melakukan sesuatu dengan elemen terakhir (sebagai lawan dari sesuatu yang berbeda dengan elemen terakhir kemudian menggunakan LINQ akan membantu di sini:

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

Jika Anda perlu melakukan sesuatu yang berbeda dengan elemen terakhir maka Anda akan membutuhkan sesuatu seperti:

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
    }
}

Meskipun Anda mungkin harus menulis pembanding khusus untuk memastikan bahwa Anda dapat mengetahui bahwa item tersebut sama dengan item yang dikembalikan oleh Last().

Pendekatan ini harus digunakan dengan hati-hati karena Lastmungkin harus dilakukan berulang kali melalui pengumpulan. Meskipun ini mungkin bukan masalah untuk koleksi kecil, jika menjadi besar itu bisa memiliki implikasi kinerja. Ini juga akan gagal jika daftar berisi item duplikat. Dalam hal ini sesuatu seperti ini mungkin lebih tepat:

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
    }
}

1
Yang saya butuhkan adalah: Ketika loop melewati item terakhir: foreach (Item menghasilkan Model.Results) {if (result == Model.Results.Last ()) {<div> last </div>; } Tampaknya Anda memiliki arti yang sama.
kecelakaan

10
Kode Anda akan diulang dua kali melalui seluruh koleksi - buruk jika koleksi tidak kecil. Lihat jawaban ini .
Shimmy Weitzhandler

54
Ini tidak akan berfungsi jika Anda memiliki duplikat di koleksi Anda. Misalnya, jika Anda bekerja dengan kumpulan string, dan ada duplikat, maka kode "berbeda dengan item terakhir" akan dieksekusi untuk setiap kemunculan item terakhir dalam daftar.
muttley91

7
Jawaban ini sudah tua, tetapi bagi orang lain yang melihat jawaban ini, Anda bisa mendapatkan elemen terakhir dan memastikan Anda tidak harus mengulang elemen dengan menggunakan: Item last = Model.Results [Model.Results.Count - 1] Hitungan properti daftar tidak memerlukan perulangan. Jika Anda memiliki duplikat dalam daftar Anda, maka gunakan saja variabel iterator dalam for for. Lama reguler untuk loop tidak buruk.
Michael Harris

Saya sarankan untuk menggunakan var last = Model.Result[Model.Result.Count - 1];untuk lebih cepat daripada menggunakanLast()
Tân

184

Bagaimana kalau kuno yang bagus untuk loop?

for (int i = 0; i < Model.Results.Count; i++) {

     if (i == Model.Results.Count - 1) {
           // this is the last item
     }
}

Atau menggunakan Linq dan foreach:

foreach (Item result in Model.Results)   
{   
     if (Model.Results.IndexOf(result) == Model.Results.Count - 1) {
             // this is the last item
     }
}

14
Begitu banyak orang yang terlalu banyak memikirkan masalah sederhana seperti ini, ketika for loop sudah benar-benar mampu melakukannya. : \
Andrew Hoffman

Solusi Linq adalah favorit mutlak saya! Terima kasih telah berbagi
mecograph

Ini adalah jawaban yang lebih tepat daripada jawaban yang diterima.
Ratul

Catatan untuk siapa pun yang ingin menggunakan solusi LINQ pada kumpulan string (atau tipe nilai): Biasanya tidak akan berhasil karena perbandingan == akan gagal jika string terakhir dalam daftar juga muncul sebelumnya dalam daftar. Ini hanya akan berfungsi jika Anda bekerja dengan daftar yang dijamin tidak memiliki string duplikat.
Tawab Wakil

Sayangnya Anda tidak dapat menggunakan solusi pintar ini jika Model.Resultsada IEnumerable. Anda dapat memanggil Count()sebelum loop tetapi itu dapat menyebabkan iterasi penuh dari urutan.
Luca Cremonesi

42

Menggunakan Last()pada tipe tertentu akan berulang melalui seluruh koleksi!
Artinya, jika Anda membuat foreachdan menelepon Last(), Anda memutar dua kali! yang saya yakin ingin Anda hindari dalam koleksi besar.

Maka solusinya adalah menggunakan do whileloop:

using var enumerator = collection.GetEnumerator();

var last = !enumerator.MoveNext();
T current;

while (!last)
{
  current = enumerator.Current;        

  //process item

  last = !enumerator.MoveNext();        
  if(last)
  {
    //additional processing for last item
  }
}

Jadi kecuali jenis koleksi adalah tipe IList<T>yang Last()fungsi akan iterate melalui semua elemen koleksi.

Uji

Jika koleksi Anda menyediakan akses acak (mis. Implement IList<T>), Anda juga dapat memeriksa item Anda sebagai berikut.

if(collection is IList<T> list)
  return collection[^1]; //replace with collection.Count -1 in pre-C#8 apps

1
Apakah Anda yakin bahwa enumerator memerlukan usingpernyataan? Saya pikir itu hanya diperlukan jika sebuah objek menangani sumber daya sistem operasi, tetapi tidak untuk struktur data yang dikelola.
Crouching Kitten

IEnumerator tidak mengimplementasikan IDisposable, jadi baris dengan menggunakan dengan menaikkan kesalahan waktu kompilasi! +1 untuk solusinya, sebagian besar waktu kita tidak bisa hanya menggunakan a untuk alih-alih foreach, karena item koleksi enumerable menghitung pada saat runtime atau urutan tidak mendukung akses acak.
Saleh

1
Yang generik tidak.
Shimmy Weitzhandler

40

Seperti yang ditunjukkan Chris, Linq akan bekerja; cukup gunakan Last () untuk mendapatkan referensi ke yang terakhir di enumerable, dan selama Anda tidak bekerja dengan referensi itu maka lakukan kode normal Anda, tetapi jika Anda bekerja dengan referensi itu maka lakukan hal tambahan Anda. Kelemahannya adalah bahwa ia akan selalu menjadi kompleksitas O (N).

Anda bisa menggunakan Count () (yang merupakan O (1) jika IEnumerable juga merupakan ICollection; ini berlaku untuk sebagian besar IEnumerables built-in yang umum), dan hybrid foreach Anda dengan counter:

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

22
foreach (var item in objList)
{
  if(objList.LastOrDefault().Equals(item))
  {

  }
}

Halo, yang ini adalah pendekatan terbaik sejauh ini! Sederhana dan to the point. Pendekatan programmer-berpikir, satu. Mengapa kita tidak memilih dan memberikan ini +1 lebih banyak dan lebih banyak!
Hanny Setiawan

1
Item terakhir harus ditemukan hanya sekali ( Promosikan memoisasi ) sebelum foreachblokir. Seperti ini: var lastItem = objList.LastOrDeafault();. Kemudian dari bagian dalam foreachlingkaran Anda bisa memeriksa dengan cara ini: f (item.Equals(lastItem)) { ... }. Dalam jawaban asli Anda, objList.LastOrDefault()akan beralih ke koleksi di setiap iterasi "foreach" ( kompleksitas Polinomial terlibat ).
AlexMelw

Jawaban yang buruk n ^ 2 kompleksitas bukannya n.
Shimmy Weitzhandler

11

Seperti yang ditunjukkan Shimmy, menggunakan Last () dapat menjadi masalah kinerja, misalnya jika koleksi Anda adalah hasil langsung dari ekspresi LINQ. Untuk mencegah beberapa iterasi, Anda bisa menggunakan metode ekstensi "ForEach" seperti ini:

var elements = new[] { "A", "B", "C" };
elements.ForEach((element, info) => {
    if (!info.IsLast) {
        Console.WriteLine(element);
    } else {
        Console.WriteLine("Last one: " + element);
    }
});

Metode ekstensi terlihat seperti ini (sebagai bonus tambahan, itu juga akan memberi tahu Anda indeks dan jika Anda melihat elemen pertama):

public static class EnumerableExtensions {
    public delegate void ElementAction<in T>(T element, ElementInfo info);

    public static void ForEach<T>(this IEnumerable<T> elements, ElementAction<T> action) {
        using (IEnumerator<T> enumerator = elements.GetEnumerator())
        {
            bool isFirst = true;
            bool hasNext = enumerator.MoveNext();
            int index = 0;
            while (hasNext)
            {
                T current = enumerator.Current;
                hasNext = enumerator.MoveNext();
                action(current, new ElementInfo(index, isFirst, !hasNext));
                isFirst = false;
                index++;
            }
        }
    }

    public struct ElementInfo {
        public ElementInfo(int index, bool isFirst, bool isLast)
            : this() {
            Index = index;
            IsFirst = isFirst;
            IsLast = isLast;
        }

        public int Index { get; private set; }
        public bool IsFirst { get; private set; }
        public bool IsLast { get; private set; }
    }
}

9

Meningkatkan jawaban Daniel Wolf lebih jauh lagi Anda bisa menumpuk di yang lain IEnumerableuntuk menghindari beberapa iterasi dan lambda seperti:

var elements = new[] { "A", "B", "C" };
foreach (var e in elements.Detailed())
{
    if (!e.IsLast) {
        Console.WriteLine(e.Value);
    } else {
        Console.WriteLine("Last one: " + e.Value);
    }
}

Implementasi metode ekstensi:

public static class EnumerableExtensions {
    public static IEnumerable<IterationElement<T>> Detailed<T>(this IEnumerable<T> source)
    {
        if (source == null)
            throw new ArgumentNullException(nameof(source));

        using (var enumerator = source.GetEnumerator())
        {
            bool isFirst = true;
            bool hasNext = enumerator.MoveNext();
            int index = 0;
            while (hasNext)
            {
                T current = enumerator.Current;
                hasNext = enumerator.MoveNext();
                yield return new IterationElement<T>(index, current, isFirst, !hasNext);
                isFirst = false;
                index++;
            }
        }
    }

    public struct IterationElement<T>
    {
        public int Index { get; }
        public bool IsFirst { get; }
        public bool IsLast { get; }
        public T Value { get; }

        public IterationElement(int index, T value, bool isFirst, bool isLast)
        {
            Index = index;
            IsFirst = isFirst;
            IsLast = isLast;
            Value = value;
        }
    }
}

1
Jawaban lainnya tidak mengulangi sumber beberapa kali, jadi itu bukan masalah yang Anda perbaiki. Anda memang telah mengizinkan penggunaan foreach, yang merupakan peningkatan.
Servy

1
@Servy maksud saya itu. Selain iterasi tunggal dari jawaban asli saya menghindari lambdas.
Fabricio Godoy

7

Implementasi iterator tidak menyediakan itu. Koleksi Anda mungkin yang dapat IListdiakses melalui indeks di O (1). Dalam hal ini Anda dapat menggunakan for-loop normal :

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

Jika Anda mengetahui jumlah, tetapi tidak dapat mengakses melalui indeks (dengan demikian, hasilnya adalah ICollection), Anda dapat menghitung sendiri dengan menambahkan sebuah idi foreachtubuh dan membandingkannya dengan panjang.

Semua ini tidak sepenuhnya elegan. Solusi Chris mungkin yang terbaik yang pernah saya lihat sejauh ini.


Dalam membandingkan kinerja penghitung Anda dalam solusi foreach vs Chris, saya bertanya-tanya mana yang lebih mahal - panggilan Last () tunggal, atau jumlah semua operasi penambahan yang ditambahkan. Saya curiga itu akan dekat.
TTT

6

Bagaimana dengan pendekatan yang lebih sederhana.

Item last = null;
foreach (Item result in Model.Results)
{
    // do something with each item

    last = result;
}

//Here Item 'last' contains the last object that came in the last of foreach loop.
DoSomethingOnLastElement(last);

2
Saya tidak tahu mengapa seseorang memilih Anda. Ini bisa diterima mengingat Anda sudah melakukan foreach dan mengeluarkan biaya o (n).
arviman

2
Terlepas dari kenyataan bahwa jawabannya sempurna untuk menemukan item terakhir, itu tidak sesuai dengan kondisi OP " ..., tentukan mana yang merupakan iterasi terakhir dari loop ". Jadi, Anda tidak dapat menentukan bahwa iterasi terakhir sebenarnya adalah yang terakhir, dan, karenanya, Anda tidak bisa menanganinya secara berbeda atau bahkan mengabaikannya. Itulah alasan seseorang menurunkan Anda. @arviman Anda sangat ingin tahu tentang hal itu.
AlexMelw

1
Anda benar, saya benar-benar merindukannya @ Andrey-WD. Saya kira solusi untuk memperbaikinya adalah memanggil "terakhir" sekali sebelum loop (tidak dapat melakukannya di dalam loop karena akan menjadi O (N ^ 2) dan kemudian memeriksa apakah referensi cocok dengan itu.
arviman

5

Pendekatan terbaik mungkin hanya akan menjalankan langkah itu setelah loop: misalnya

foreach(Item result in Model.Results)
{
   //loop logic
}

//Post execution logic

Atau jika Anda perlu melakukan sesuatu untuk hasil terakhir

foreach(Item result in Model.Results)
{
   //loop logic
}

Item lastItem = Model.Results[Model.Results.Count - 1];

//Execute logic on lastItem here

3

Jawaban yang diterima tidak akan berfungsi untuk duplikat dalam koleksi. Jika Anda diatur pada foreach, Anda bisa menambahkan variabel pengindeksan Anda sendiri.

int last = Model.Results.Count - 1;
int index = 0;
foreach (Item result in Model.Results)
{
    //Do Things

    if (index == last)
        //Do Things with the last result

    index++;
}


1

".Last ()" tidak berfungsi untuk saya, jadi saya harus melakukan sesuatu seperti ini:

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 */
);

1

Membuat beberapa penyesuaian kecil pada kode excelent dari Jon Skeet, Anda bahkan dapat membuatnya lebih pintar dengan memungkinkan akses ke item sebelumnya dan berikutnya. Tentu saja ini berarti Anda harus membaca dulu 1 item dalam implementasi. Untuk alasan kinerja, item sebelumnya dan berikutnya hanya dipertahankan untuk item iterasi saat ini. Bunyinya seperti ini:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// Based on source: http://jonskeet.uk/csharp/miscutil/

namespace Generic.Utilities
{
    /// <summary>
    /// Static class to make creation easier. If possible though, use the extension
    /// method in SmartEnumerableExt.
    /// </summary>
    public static class SmartEnumerable
    {
        /// <summary>
        /// Extension method to make life easier.
        /// </summary>
        /// <typeparam name="T">Type of enumerable</typeparam>
        /// <param name="source">Source enumerable</param>
        /// <returns>A new SmartEnumerable of the appropriate type</returns>
        public static SmartEnumerable<T> Create<T>(IEnumerable<T> source)
        {
            return new SmartEnumerable<T>(source);
        }
    }

    /// <summary>
    /// Type chaining an IEnumerable&lt;T&gt; to allow the iterating code
    /// to detect the first and last entries simply.
    /// </summary>
    /// <typeparam name="T">Type to iterate over</typeparam>
    public class SmartEnumerable<T> : IEnumerable<SmartEnumerable<T>.Entry>
    {

        /// <summary>
        /// Enumerable we proxy to
        /// </summary>
        readonly IEnumerable<T> enumerable;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="enumerable">Collection to enumerate. Must not be null.</param>
        public SmartEnumerable(IEnumerable<T> enumerable)
        {
            if (enumerable == null)
            {
                throw new ArgumentNullException("enumerable");
            }
            this.enumerable = enumerable;
        }

        /// <summary>
        /// Returns an enumeration of Entry objects, each of which knows
        /// whether it is the first/last of the enumeration, as well as the
        /// current value and next/previous values.
        /// </summary>
        public IEnumerator<Entry> GetEnumerator()
        {
            using (IEnumerator<T> enumerator = enumerable.GetEnumerator())
            {
                if (!enumerator.MoveNext())
                {
                    yield break;
                }
                bool isFirst = true;
                bool isLast = false;
                int index = 0;
                Entry previous = null;

                T current = enumerator.Current;
                isLast = !enumerator.MoveNext();
                var entry = new Entry(isFirst, isLast, current, index++, previous);                
                isFirst = false;
                previous = entry;

                while (!isLast)
                {
                    T next = enumerator.Current;
                    isLast = !enumerator.MoveNext();
                    var entry2 = new Entry(isFirst, isLast, next, index++, entry);
                    entry.SetNext(entry2);
                    yield return entry;

                    previous.UnsetLinks();
                    previous = entry;
                    entry = entry2;                    
                }

                yield return entry;
                previous.UnsetLinks();
            }
        }

        /// <summary>
        /// Non-generic form of GetEnumerator.
        /// </summary>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        /// <summary>
        /// Represents each entry returned within a collection,
        /// containing the value and whether it is the first and/or
        /// the last entry in the collection's. enumeration
        /// </summary>
        public class Entry
        {
            #region Fields
            private readonly bool isFirst;
            private readonly bool isLast;
            private readonly T value;
            private readonly int index;
            private Entry previous;
            private Entry next = null;
            #endregion

            #region Properties
            /// <summary>
            /// The value of the entry.
            /// </summary>
            public T Value { get { return value; } }

            /// <summary>
            /// Whether or not this entry is first in the collection's enumeration.
            /// </summary>
            public bool IsFirst { get { return isFirst; } }

            /// <summary>
            /// Whether or not this entry is last in the collection's enumeration.
            /// </summary>
            public bool IsLast { get { return isLast; } }

            /// <summary>
            /// The 0-based index of this entry (i.e. how many entries have been returned before this one)
            /// </summary>
            public int Index { get { return index; } }

            /// <summary>
            /// Returns the previous entry.
            /// Only available for the CURRENT entry!
            /// </summary>
            public Entry Previous { get { return previous; } }

            /// <summary>
            /// Returns the next entry for the current iterator.
            /// Only available for the CURRENT entry!
            /// </summary>
            public Entry Next { get { return next; } }
            #endregion

            #region Constructors
            internal Entry(bool isFirst, bool isLast, T value, int index, Entry previous)
            {
                this.isFirst = isFirst;
                this.isLast = isLast;
                this.value = value;
                this.index = index;
                this.previous = previous;
            }
            #endregion

            #region Methods
            /// <summary>
            /// Fix the link to the next item of the IEnumerable
            /// </summary>
            /// <param name="entry"></param>
            internal void SetNext(Entry entry)
            {
                next = entry;
            }

            /// <summary>
            /// Allow previous and next Entry to be garbage collected by setting them to null
            /// </summary>
            internal void UnsetLinks()
            {
                previous = null;
                next = null;
            }

            /// <summary>
            /// Returns "(index)value"
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
                return String.Format("({0}){1}", Index, Value);
            }
            #endregion

        }
    }
}

1

Cara mengonversi foreachuntuk bereaksi ke elemen terakhir:

List<int> myList = new List<int>() {1, 2, 3, 4, 5};
Console.WriteLine("foreach version");
{
    foreach (var current in myList)
    {
        Console.WriteLine(current);
    }
}
Console.WriteLine("equivalent that reacts to last element");
{
    var enumerator = myList.GetEnumerator();
    if (enumerator.MoveNext() == true) // Corner case: empty list.
    {
        while (true)
        {
            int current = enumerator.Current;

            // Handle current element here.
            Console.WriteLine(current);

            bool ifLastElement = (enumerator.MoveNext() == false);
            if (ifLastElement)
            {
                // Cleanup after last element
                Console.WriteLine("[last element]");
                break;
            }
        }
    }
    enumerator.Dispose();
}

1

Hanya menyimpan nilai sebelumnya dan bekerja dengannya di dalam loop. Kemudian pada akhirnya nilai 'sebelumnya' akan menjadi item terakhir, membiarkan Anda menanganinya secara berbeda. Tidak diperlukan penghitungan atau perpustakaan khusus.

bool empty = true;
Item previousItem;

foreach (Item result in Model.Results)
{
    if (!empty)
    {
        // We know this isn't the last item because it came from the previous iteration
        handleRegularItem(previousItem);
    }

    previousItem = result;
    empty = false;
}

if (!empty)
{
    // We know this is the last item because the loop is finished
    handleLastItem(previousItem);
}

1

Anda bisa menggunakan for for loop dan tidak perlu menambahkan ekstra ifdi dalam fortubuh:

for (int i = 0; i < Model.Results.Count - 1; i++) {
    var item = Model.Results[i];
}

The -1dalam forkondisi mengurus melewatkan item terakhir.


-1 pada loop for tidak menangani melewatkan item terakhir. Anda akan mendapatkan IndexOutOfRangeException jika Anda tidak menyertakan -1.
Jaa H


0

Untuk melakukan sesuatu yang tambahan untuk setiap elemen kecuali yang terakhir, pendekatan berbasis fungsi dapat digunakan.

delegate void DInner ();

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

Pendekatan ini memiliki kelemahan yang jelas: kurang kejelasan kode untuk kasus yang lebih kompleks. Memanggil delegasi mungkin tidak terlalu efektif. Pemecahan masalah mungkin tidak mudah. Sisi baiknya - coding itu menyenangkan!

Karena itu, saya akan menyarankan menggunakan polos untuk loop dalam kasus sepele, jika Anda tahu bahwa jumlah koleksi Anda tidak terlalu lambat.


0

Cara lain, yang tidak saya lihat diposting, adalah dengan menggunakan Antrian. Ini analog dengan cara mengimplementasikan metode SkipLast () tanpa mengulangi lebih dari yang diperlukan. Cara ini juga akan memungkinkan Anda melakukan ini pada sejumlah item terakhir.

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);
}

Untuk memanggil ini Anda akan melakukan hal berikut:

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

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

                }

0

Anda dapat membuat metode ekstensi yang didedikasikan khusus untuk ini:

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);
        }
    }

dan Anda dapat menggunakannya seperti ini:

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

0

Berdasarkan pada tanggapan Shimmy, saya menciptakan metode ekstensi yang merupakan solusi yang semua orang inginkan. Ini sederhana, mudah digunakan, dan hanya mengulang koleksi sekali.

internal static class EnumerableExtensions
{
    public static void ForEachLast<T>(this IEnumerable<T> collection, Action<T>? actionExceptLast = null, Action<T>? actionOnLast = null)
    {
        using var enumerator = collection.GetEnumerator();
        var isNotLast = enumerator.MoveNext();
        while (isNotLast)
        {
            var current = enumerator.Current;
            isNotLast = enumerator.MoveNext();
            var action = isNotLast ? actionExceptLast : actionOnLast;
            action?.Invoke(current);
        }
    }
}

Ini bekerja pada siapa saja IEnumerable<T>. Penggunaannya terlihat seperti ini:

var items = new[] {1, 2, 3, 4, 5};
items.ForEachLast(i => Console.WriteLine($"{i},"), i => Console.WriteLine(i));

Outputnya seperti:

1,
2,
3,
4,
5

Selain itu, Anda dapat menjadikan ini sebagai Selectmetode gaya. Kemudian, gunakan kembali ekstensi itu di ForEach. Kode itu terlihat seperti ini:

internal static class EnumerableExtensions
{
    public static void ForEachLast<T>(this IEnumerable<T> collection, Action<T>? actionExceptLast = null, Action<T>? actionOnLast = null) =>
        // ReSharper disable once IteratorMethodResultIsIgnored
        collection.SelectLast(i => { actionExceptLast?.Invoke(i); return true; }, i => { actionOnLast?.Invoke(i); return true; }).ToArray();

    public static IEnumerable<TResult> SelectLast<T, TResult>(this IEnumerable<T> collection, Func<T, TResult>? selectorExceptLast = null, Func<T, TResult>? selectorOnLast = null)
    {
        using var enumerator = collection.GetEnumerator();
        var isNotLast = enumerator.MoveNext();
        while (isNotLast)
        {
            var current = enumerator.Current;
            isNotLast = enumerator.MoveNext();
            var selector = isNotLast ? selectorExceptLast : selectorOnLast;
            //https://stackoverflow.com/a/32580613/294804
            if (selector != null)
            {
                yield return selector.Invoke(current);
            }
        }
    }
}

-1

Kami dapat memeriksa item terakhir dalam lingkaran.

foreach (Item result in Model.Results)
{
    if (result==Model.Results.Last())
    {
        // do something different with the last item
    }
}

-2
foreach (DataRow drow in ds.Tables[0].Rows)
            {
                cnt_sl1 = "<div class='col-md-6'><div class='Slider-img'>" +
                          "<div class='row'><img src='" + drow["images_path"].ToString() + "' alt='' />" +
                          "</div></div></div>";
                cnt_sl2 = "<div class='col-md-6'><div class='Slider-details'>" +
                          "<p>" + drow["situation_details"].ToString() + "</p>" +
                          "</div></div>";
                if (i == 0)
                {
                    lblSituationName.Text = drow["situation"].ToString();
                }
                if (drow["images_position"].ToString() == "0")
                {
                    content += "<div class='item'>" + cnt_sl1 + cnt_sl2 + "</div>";
                    cnt_sl1 = "";
                    cnt_sl2 = "";
                }
                else if (drow["images_position"].ToString() == "1")
                {
                    content += "<div class='item'>" + cnt_sl2 + cnt_sl1 + "</div>";
                    cnt_sl1 = "";
                    cnt_sl2 = "";
                }
                i++;
            }

(!) Tidak peduli seberapa baik atau buruk kode Anda. Tanpa penjelasan, biasanya tidak ada nilainya.
AlexMelw

Juga sepertinya terlalu direkayasa.
mecograph

-3

Anda bisa melakukan ini:

foreach (DataGridViewRow dgr in product_list.Rows)
{
    if (dgr.Index == dgr.DataGridView.RowCount - 1)
    {
        //do something
    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.