[C#] foreach avec liste générique, détection de la première itération lors de l'utilisation du type de valeur


Answers

Il y a quelque temps j'ai écrit SmartEnumerable (qui fait partie de MiscUtil) qui vous permet de savoir si l'élément en cours est le premier ou le dernier, ainsi que son index. Cela peut vous aider ... cela fait partie de MiscUtil, qui est open source - vous pouvez prendre seulement SmartEnumerable sous la même licence, bien sûr.

Exemple de code (c'n'p de la page Web):

using System;
using System.Collections.Generic;

using MiscUtil.Collections;

class Example
{
    static void Main(string[] args)
    {
        List<string> list = new List<string>();
        list.Add("a");
        list.Add("b");
        list.Add("c");
        list.Add("d");
        list.Add("e");

        foreach (SmartEnumerable<string>.Entry entry in
                 new SmartEnumerable<string>(list))
        {
            Console.WriteLine ("{0,-7} {1} ({2}) {3}",
                               entry.IsLast  ? "Last ->" : "",
                               entry.Value,
                               entry.Index,
                               entry.IsFirst ? "<- First" : "");
        }
    }
}

EDIT: Notez que bien qu'il fonctionne avec des types de référence avec des références distinctes, il échouera toujours si vous lui donnez une liste où la première référence surgit ailleurs dans la liste.

Question

Lorsque je passe une liste générique, je veux souvent faire quelque chose de différent pour le premier élément de la liste:

List<object> objs = new List<object>
{
    new Object(),
    new Object(),
    new Object(),
    new Object()
};

foreach (object o in objs)
{
    if (o == objs.First())
    {
        System.Diagnostics.Debug.WriteLine("First object - do something special");
    }
    else
    {
        System.Diagnostics.Debug.WriteLine("object Do something else");
    }
}

Cela va produire:

    First object - do something special
    object Do something else
    object Do something else
    object Do something else

Tout cela est bien et dandy.

Cependant, si ma liste générique est de type valeur, cette approche échouera.

List<int> ints = new List<int> { 0, 0, 0, 0 };
foreach (int i in ints)
{
    if (i == ints.First())
    {
        System.Diagnostics.Debug.WriteLine("First int - do something special");
    }
    else
    {
        System.Diagnostics.Debug.WriteLine("int Do something else");
    }
}

Cela va produire:

    First int - do something special
    First int - do something special
    First int - do something special
    First int - do something special

Maintenant je sais que je pourrais recoder ceci pour ajouter une variable boolean ou traditionnelle for boucle, mais je me demande s'il y a moyen de savoir si une boucle foreach est sur la première itération de sa boucle.




Modification à partir d'une autre réponse:

IList<object> objs = new List<object>
{
    new Object(),
    new Object(),
    new Object(),
    new Object()
};

// to access first element: objs[0]
// to access last element: objs[objs.Count - 1]

System.Diagnostics.Debug.WriteLine("First object - do something special");

foreach (object o in objs.Skip(1))
{
    System.Diagnostics.Debug.WriteLine("object Do something else");
}

Lien de référence sur:

Utilisation de Skip : Méthode Enumerable.Skip (IEnumerable, Int32)

Utilisation de IList<T> : List ou IList




Au lieu de if (i == ints.First()) , cela fonctionne-t-il si vous utilisez if (i.Equals(ints.First()) ?




Puisque vous utilisez déjà LINQ, vous pouvez le faire:

var list = new List<Int32>();

// do something with list.First();

foreach (var item in list.Skip(1))
{
    // do other stuff
}