Foreach döngüsü, döngünün son yinelemesinin hangisi olduğunu belirleyin


233

Bir foreachdöngü var ve son öğe List, örneğin seçildiğinde bazı mantık yürütmek gerekir :

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

Döngü ve sayaçlar için kullanmadan hangi döngünün en son olduğunu öğrenebilir miyim?


1
İlgili bir soruya gönderdiğim bir çözüm için cevabımı burada bulabilirsiniz .
Brian Gideon

Yanıtlar:


294

Son öğeyle ilgili bir şey yapmanız gerekiyorsa (son öğeyle farklı bir şeyin aksine) LINQ kullanmak burada yardımcı olacaktır:

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

Son öğeyle farklı bir şey yapmanız gerekiyorsa, aşağıdaki gibi bir şeye ihtiyacınız olacaktır:

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

Yine de, öğenin döndürülen öğeyle aynı olduğunu söyleyebilmeniz için özel bir karşılaştırıcı yazmanız gerekir Last().

Bu yaklaşım Last, toplama yoluyla yinelemek zorunda kalabileceği için dikkatli kullanılmalıdır . Bu, küçük koleksiyonlar için bir sorun olmasa da, eğer büyük olursa performans sonuçları olabilir. Liste yinelenen öğeler içeriyorsa da başarısız olur. Bu durumlarda böyle bir şey daha uygun olabilir:

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
İhtiyacım olan şey: Döngü son öğesinden geçerken: foreach (Model.Results öğesinde sonuç) {if (sonuç == Model.Results.Last ()) {<div> son </div>; } Görünüşe göre hemen hemen aynı şey demek istiyorsun.
aksilik

10
Kod, tüm koleksiyon boyunca iki kez yinelenir - koleksiyon küçük değilse kötü. Bu cevaba bakınız .
Shimmy Weitzhandler

54
Koleksiyonunuzda kopyalar varsa bu gerçekten işe yaramaz. Örneğin, bir dizeler koleksiyonuyla çalışıyorsanız ve yinelenen kopyalar varsa, listedeki son öğenin her örneği için bu "son öğeden farklı" kodu yürütülür.
muttley91

7
Bu cevap eskidir, ancak bu cevaba bakan diğerleri için, son öğeyi alabilir ve aşağıdakileri kullanarak öğeler arasında gezinmek zorunda kalmayacağınızdan emin olabilirsiniz: Item last = Model.Results [Model.Results.Count - 1] Sayı bir listenin özelliği döngü gerektirmez. Listenizde kopyalar varsa, for döngüsünde bir yineleyici değişkeni kullanın. Döngüler için düzenli eski kötü değil.
Michael Harris

Kullanmaktan var last = Model.Result[Model.Result.Count - 1];daha hızlı kullanmanı öneririmLast()
Tân

184

Döngü için iyi bir eski modaya ne dersiniz?

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

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

Veya Linq ve foreach kullanarak:

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

14
Bu yüzden basit bir problemi düşünen pek çok kişi, for döngüsü zaten zaten yapabiliyorsa. : \
Andrew Hoffman

Linq çözümü benim mutlak favorim!
Paylaştığınız

Bu, kabul edilen yanıttan daha uygun bir cevaptır.
Ratul

Dizeleri (veya değer türlerini) bir koleksiyonda LINQ çözümünü kullanmak isteyen herkese dikkat edin: Listedeki son dize de listede daha erken görünüyorsa == karşılaştırma başarısız olur. Yalnızca yinelenen dizeleri olmadığı garanti edilen bir listeyle çalışıyorsanız çalışır.
Tawab Wakil

Ne yazık ki bu akıllı çözüm kullanamazsınız Model.Resultsbir olduğunu IEnumerable. Döngüden Count()önce çağırabilirsiniz , ancak bu, dizinin tam yinelemesine neden olabilir.
Luca Cremonesi

42

Last()Belirli türleri kullanarak tüm koleksiyon döngü olacak!
Yani bir foreachve arama Last()yaparsanız, iki kez döngü ! eminim ki büyük koleksiyonlarda sakınmak istersiniz.

Sonra çözüm bir do whiledöngü kullanmaktır :

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

Toplama tür türündeki sürece Yani fonksiyon tüm toplama elemanları aracılığıyla yineleme olacak.IList<T>Last()

Ölçek

Koleksiyonunuz rastgele erişim sağlıyorsa (örn. Uygular IList<T>), öğenizi aşağıdaki gibi de kontrol edebilirsiniz.

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

1
Sayıcının bir usingifadeye ihtiyacı olduğundan emin misiniz ? Bunun yalnızca bir nesne işletim sistemi kaynaklarını işliyorsa gerekli olduğunu düşündüm, ancak yönetilen veri yapıları için değil.
Çömelmiş Yavru Kedi

IEnumerator IDisposable uygulamaz, bu nedenle ile kullanarak satır derleme zamanı hatası yükseltmek! +1 için çözüm, çoğu zaman sadece foreach yerine bir for kullanamayız, çünkü numaralandırılabilir koleksiyon öğeleri çalışma zamanında hesaplanır veya sıra rastgele erişimi desteklemez.
Saleh


40

Chris'in gösterdiği gibi, Linq çalışacak; numaralandırılabilir sonuncusuna bir referans almak için Last () kullanın ve bu referans ile çalışmadığınız sürece normal kodunuzu yapın, ancak bu referansla çalışıyorsanız, ekstra bir şey yapın. Bunun dezavantajı, her zaman O (N) -sompleksite olmasıdır.

Bunun yerine Count () (IEnumerable da bir ICollection ise O (1) 'i kullanabilirsiniz; bu, yaygın yerleşik IEnumerables'ın çoğu için geçerlidir) ve önbelleğinizi bir sayaçla hibritleyebilirsiniz:

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))
  {

  }
}

Merhaba, bu şimdiye kadarki en iyi yaklaşım! Basit ve noktaya. Bir programcı-şey yaklaşım, biri. Neden bunu + 1 ve daha fazla vermiyoruz?
Hanny Setiawan

1
Son öğe, bloktan önce yalnızca bir kez ( Notu yükselt ) bulunmalıdır foreach. Bunun gibi: var lastItem = objList.LastOrDeafault();. Sonra içinden foreachdöngü sen bu şekilde kontrol edebilir: f (item.Equals(lastItem)) { ... }. Orijinal cevabınızda, objList.LastOrDefault()her "foreach" yinelemesinde ( Polinom karmaşıklığı söz konusudur ) koleksiyon üzerindeki yineleme .
AlexMelw

Kötü cevap. n yerine n ^ 2 karmaşıklığı.
Shimmy Weitzhandler

11

Shimmy'nin işaret ettiği gibi, örneğin koleksiyonunuz bir LINQ ifadesinin canlı sonucu ise Last () kullanmak bir performans sorunu olabilir. Birden çok yinelemeyi önlemek için, aşağıdaki gibi bir "ForEach" uzantı yöntemi kullanabilirsiniz:

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

Uzantı yöntemi şu şekilde görünür (ek bir bonus olarak, size dizini ve ilk öğeye bakıyorsanız da söyler):

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

Daniel Wolf yanıtını daha da geliştirmek , IEnumerablebirden fazla yinelemeden ve lambdadan kaçınmak için başka bir tane üzerine yığınlayabilirsiniz:

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

Uzantı yöntemi uygulaması:

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
Diğer cevap kaynağı defalarca yinelemez, bu yüzden düzelttiğiniz bir sorun değildir. Gerçekten kullanımına izin verdiniz foreach, ki bu bir gelişme.
Servy

1
@Servy Bunu demek istiyorum. Orijinal cevaptan tek bir yinelemenin yanı sıra lambdalardan kaçıyorum.
Fabricio Godoy

7

Yineleyici uygulaması bunu sağlamaz. Koleksiyonunuz IListO (1) içindeki bir dizin aracılığıyla erişilebilen bir koleksiyon olabilir . Bu durumda normal bir fordöngü kullanabilirsiniz :

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

Count biliyorum ama endeksleri (böylece, sonuç ise yoluyla erişemediği takdirde ICollection), bir artırarak kendinizi sayabilir iiçindeforeach 'nin beden ve uzunluğuna karşılaştırarak.

Bütün bunlar tamamen zarif değil. Chris'in çözümü şimdiye kadar gördüğüm en güzel çözüm olabilir.


Tezgahınızın foreach fikri ile Chris'in çözümü arasındaki performansını karşılaştırırken hangisinin daha fazla paraya mal olacağını merak ediyorum - tek bir Last () çağrısı veya eklenen tüm arttırma işlemlerinin toplamı. Yakın olacağından şüpheleniyorum.
TTT

6

Biraz daha basit yaklaşıma ne dersiniz?

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
Birinin neden sana niye oy verdiğini bilmiyorum. Zaten bir foreach uyguladığınızı ve o (n) 'nin maliyetini ödediğinizi göz önünde bulundurarak bu kabul edilebilir.
arviman

2
Cevabın son öğeyi bulmak için mükemmel olmasına rağmen, OP'nin " ..., döngünün son yinelemesinin hangisi olduğunu belirle " durumuna uymuyor . Böylece, son yinelemenin aslında sonuncusu olduğunu belirleyemezsiniz ve bu nedenle, onu farklı şekilde ele alamazsınız, hatta görmezden gelemezsiniz. Birinin seni küçümsemesinin nedeni budur. @arviman çok merak ediyordun.
AlexMelw

1
Haklısın, tamamen kaçırdım @ Andrey-WD. Düzeltmek için çözüm döngü önce bir kez "son" çağırmak sanırım (O (N ^ 2) olduğu gibi döngü içinde yapamazsınız ve sonra referans eşleşip eşleşmediğini kontrol edin.
arviman

5

En iyi yaklaşım muhtemelen bu adımı döngüden sonra yürütmek olacaktır: ör.

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

//Post execution logic

Veya son sonuca kadar bir şeyler yapmanız gerekiyorsa

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

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

//Execute logic on lastItem here

3

Kabul edilen cevap, koleksiyondaki kopyalar için çalışmaz. Ayarlıysanız foreach, sadece kendi indeksleme değişken (ler) inizi ekleyebilirsiniz.

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 ()" benim için çalışmadı, bu yüzden böyle bir şey yapmak zorunda kaldım:

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

Mükemmel Jon Skeet kodunda bazı küçük ayarlamalar yaparak, önceki ve sonraki öğeye erişime izin vererek daha akıllı hale getirebilirsiniz. Tabii ki bu uygulamada 1 maddeyi okumak zorunda kalacağınız anlamına gelir. Performans nedenleriyle, önceki ve sonraki öğe yalnızca geçerli yineleme öğesi için korunur. Bu böyle devam ediyor:

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

foreachSon öğeye tepki vermek için nasıl dönüştürülür :

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

Sadece önceki değeri saklayın ve onunla döngü içinde çalışın. Sonunda 'önceki' değer son öğe olacak ve farklı ele almanıza izin verecektir. Sayım veya özel kütüphane gerekmez.

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

Sadece bir for döngüsü kullanabilirsiniz ifve forvücudun içine fazladan bir şey eklemenize gerek yoktur :

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

-1İçinde fordurumun son öğeyi atlama ilgilenir.


For döngüsündeki -1, son öğeyi atlamakla ilgilenmez. -1 eklemediyseniz bir IndexOutOfRangeException alıyorsunuz.
Jaa H


0

Sonuncusu hariç her bir öğeye ek bir şey yapmak için fonksiyon tabanlı yaklaşım kullanılabilir.

delegate void DInner ();

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

Bu yaklaşımın belirgin dezavantajları vardır: daha karmaşık durumlar için daha az kod netliği. Delegeleri aramak çok etkili olmayabilir. Sorun giderme işlemi kolay olmayabilir. Parlak tarafı - kodlama eğlenceli!

Bunu söyledikten sonra, koleksiyonunuzun sayısının çok yavaş olmadığını biliyorsanız, önemsiz durumlarda döngüler için düz kullanmanızı öneririm.


0

Yayınlanmadığımı başka bir yol, bir Kuyruk kullanmaktır. SkipLast () yöntemini gerekenden daha fazla yinelemeden uygulamanın bir yoluna benzer. Bu şekilde, bunu istediğiniz sayıda son öğe üzerinde de yapabilirsiniz.

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

Bunu aramak için aşağıdakileri yaparsınız:

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

Özellikle buna adanmış bir uzatma yöntemi yapabilirsiniz:

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

ve şu şekilde kullanabilirsiniz:

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

0

@ Shimmy'nin yanıtına dayanarak, herkesin istediği çözüm olan bir uzantı yöntemi oluşturdum. Basit, kullanımı kolay ve koleksiyonda sadece bir kez dolaşıyor.

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

Bu herhangi bir üzerinde çalışır IEnumerable<T>. Kullanım şöyle görünür:

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

Çıktı şöyle görünür:

1,
2,
3,
4,
5

Ayrıca, bunu bir Selectstil yöntemine dönüştürebilirsiniz . Ardından, bu uzantıyı ForEach. Bu kod şöyle görünür:

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

Döngüdeki son öğeyi kontrol edebiliriz.

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

(!) Kodunuz ne kadar iyi veya ne kadar kötü olursa olsun. Bir açıklama olmadan genellikle değeri yoktur.
AlexMelw

Ayrıca aşırı tasarlanmış gibi görünüyor.
mecograph

-3

Bunu şöyle yapabilirsiniz:

foreach (DataGridViewRow dgr in product_list.Rows)
{
    if (dgr.Index == dgr.DataGridView.RowCount - 1)
    {
        //do something
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.