400 votes

Comment puis-je retourner un IEnumerable vide ?

Étant donné le code suivant et les suggestions données dans cette question J'ai décidé de modifier cette méthode originale et de demander s'il y a des valeurs dans l'IEnumarable, de le retourner, sinon de retourner un IEnumerable sans valeurs.

Voici la méthode :

public IEnumerable<Friend> FindFriends()
        {
            //Many thanks to Rex-M for his help with this one.
            //https://stackoverflow.com/users/67/rex-m

            return doc.Descendants("user").Select(user => new Friend
            {
                ID = user.Element("id").Value,
                Name = user.Element("name").Value,
                URL = user.Element("url").Value,
                Photo = user.Element("photo").Value
            });
        }

Comme tout se trouve dans l'instruction de retour, je ne sais pas comment faire. Est-ce que quelque chose comme ceci fonctionnerait ?

public IEnumerable<Friend> FindFriends()
        {
            //Many thanks to Rex-M for his help with this one.
            //https://stackoverflow.com/users/67/rex-m
            if (userExists)
            {
                return doc.Descendants("user").Select(user => new Friend
                {
                    ID = user.Element("id").Value,
                    Name = user.Element("name").Value,
                    URL = user.Element("url").Value,
                    Photo = user.Element("photo").Value
                });
            }
            else
            { 
                return new IEnumerable<Friend>();
            }
        }

La méthode ci-dessus ne fonctionne pas, et en fait elle n'est pas censée fonctionner ; je pense simplement qu'elle illustre mes intentions. Je pense que je dois préciser que le code ne fonctionne pas car on ne peut pas créer une instance d'une classe abstraite.

Voici le code d'appel, je ne veux pas qu'il reçoive un IEnumerable nul à tout moment :

private void SetUserFriends(IEnumerable<Friend> list)
        {
            int x = 40;
            int y = 3;

            foreach (Friend friend in list)
            {
                FriendControl control = new FriendControl();
                control.ID = friend.ID;
                control.URL = friend.URL;
                control.SetID(friend.ID);
                control.SetName(friend.Name);
                control.SetImage(friend.Photo);

                control.Location = new Point(x, y);
                panel2.Controls.Add(control);

                y = y + control.Height + 4;
            } 

        }

Merci pour votre temps.

2 votes

En regardant le code ici, vous devriez utiliser yield return et yield break.

680voto

Michael Mrozek Points 44120

Vous pouvez utiliser list ?? Enumerable.Empty<Friend>() ou avoir FindFriends retourner Enumerable.Empty<Friend>()

Vous pouvez le trouver sous la rubrique System.Linq espace de noms.

7 votes

Est-ce que ça changerait les choses s'il revenait, disons, new List<Friend>() puisqu'il sera transformé en IEnumerable<Friend> lorsqu'il est renvoyé par cette méthode ?

83 votes

new List<Friend>() est une opération plus coûteuse car elle crée une instance d'une liste (et lui alloue de la mémoire dans le processus).

196voto

LukeH Points 110965

Vous pourriez retourner Enumerable.Empty<T>() .

121voto

Kefir Points 906

En ce qui me concerne, le moyen le plus élégant est yield break

9 votes

Mais c'est si vous utilisez le rendement et autres, n'est-ce pas ?

16 votes

+1 car son code devrait correctement utiliser yield pour la façon dont il travaille avec IEnumerable.

6 votes

Pardonnez mon ignorance sur le sujet, mais pourriez-vous illustrer comment utiliser le yield break dans ce contexte ? J'ai vu des exemples uniquement dans des boucles for, mais cela ne me donne pas une image claire.

9voto

Chaos Points 56

Ce n'est bien sûr qu'une question de préférence personnelle, mais j'écrirais cette fonction en utilisant le retour de rendement :

public IEnumerable<Friend> FindFriends()
{
    //Many thanks to Rex-M for his help with this one.
    //http://stackoverflow.com/users/67/rex-m
    if (userExists)
    {
        foreach(var user in doc.Descendants("user"))
        {
            yield return new Friend
                {
                    ID = user.Element("id").Value,
                    Name = user.Element("name").Value,
                    URL = user.Element("url").Value,
                    Photo = user.Element("photo").Value
                }
        }
    }
}

1voto

James Curran Points 55356

Je pense que le moyen le plus simple serait

 return new Friend[0];

Les exigences de retour sont simplement que la méthode retourne un objet qui implémente IEnumerable<Friend> . Le fait que dans des circonstances différentes, vous renvoyez deux types d'objets différents n'est pas pertinent, tant que les deux implémentent IEnumerable.

5 votes

Enumerable.Empty<T> retourne en fait un tableau vide de T (T[0]), avec l'avantage de réutiliser le même tableau vide. Notez que cette approche n'est pas idéale pour les tableaux non vides, car les éléments peuvent être modifiés (par contre un tableau ne peut pas être redimensionné, le redimensionnement implique la création d'une nouvelle instance).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X