Wie kann ich eine leere IEnumerable zurückgeben?


328

Angesichts des folgenden Codes und der in dieser Frage gegebenen Vorschläge habe ich beschlossen, diese ursprüngliche Methode zu ändern und zu fragen, ob Werte in IEnumarable vorhanden sind. Geben Sie sie zurück, wenn nicht, geben Sie eine IEnumerable ohne Werte zurück.

Hier ist die Methode:

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

Da sich alles in der return-Anweisung befindet, weiß ich nicht, wie ich das tun könnte. Würde so etwas funktionieren?

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

Die obige Methode funktioniert nicht und sollte es auch nicht. Ich fühle nur, dass es meine Absichten veranschaulicht. Ich denke, ich sollte angeben, dass der Code nicht funktioniert, da Sie keine Instanz einer abstrakten Klasse erstellen können.

Hier ist der aufrufende Code, ich möchte nicht, dass er zu irgendeinem Zeitpunkt eine Null-IEnumerable erhält:

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

        }

Vielen Dank für Ihre Zeit.


2
Wenn Sie sich den Code hier ansehen, sollten Sie Yield Return und Yield Break verwenden.
Chris Marisic

Antworten:


574

Sie können verwenden list ?? Enumerable.Empty<Friend>()oder FindFriendszurückgebenEnumerable.Empty<Friend>()


7
Würde es die Dinge ändern, wenn er zurückkehren würde, sagen wir, new List<Friend>()da es gegossen wird, IEnumerable<Friend>wenn es von dieser Methode zurückgegeben wird?
Sarah Vessels

73
new List<Friend>()ist eine teurere Operation, weil sie eine Instanz einer Liste erstellen würde (und dabei Speicher dafür zuweisen würde)
Igor Pashchuk


105

Für mich ist der eleganteste Weg yield break


8
Aber das ist, wenn Sie Ertragsrendite und so verwenden, nicht wahr?
Svish

15
+1 als sein Code sollte Ausbeute für die Art und Weise verwenden, wie er mit IEnumerable arbeitet
Chris Marisic

6
Verzeihen Sie meine Unwissenheit zu diesem Thema, aber können Sie bitte veranschaulichen, wie die Ertragsunterbrechung in diesem Zusammenhang verwendet wird? Ich habe nur Beispiele für for-Schleifen gesehen, aber das ergibt für mich kein klares Bild.
Sergio Tapia

Die Antwort wurde mit einem Beispiel aktualisiert. Wirklich ist die eleganteste Art, es zu tun, würde ich zustimmen. :)
Johny Skovdal

4
Bearbeiten wurde in Peer - Review abgelehnt, so ist hier das Beispiel , das ich sprach über @Pyritie - die Formatierung obwohl vermasselt wird, so dass ich es zu hinzugefügt pastebin.com/X9Z49Vq1 auch:public IEnumerable<Friend> FindFriends() { if(!userExists) yield break; foreach(var descendant in 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 })) { yield return descendant; } }
Johny Skovdal

8

Das ist natürlich nur eine Frage der persönlichen Präferenz, aber ich würde diese Funktion mit Yield Return schreiben:

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

1

Ich denke, der einfachste Weg wäre

 return new Friend[0];

Die Anforderungen der Rückgabe sind lediglich, dass die Methode ein Objekt zurückgibt, das implementiert wird IEnumerable<Friend>. Die Tatsache, dass Sie unter verschiedenen Umständen zwei verschiedene Arten von Objekten zurückgeben, ist irrelevant, solange beide IEnumerable implementieren.


5
Enumerable.Empty <T> gibt tatsächlich ein leeres Array von T (T [0]) zurück, mit dem Vorteil, dass dasselbe leere Array wiederverwendet wird. Beachten Sie, dass dieser Ansatz nicht für nicht leere Arrays geeignet ist, da die Elemente geändert werden können (die Größe eines Arrays kann jedoch nicht geändert werden, bei der Größenänderung wird eine neue Instanz erstellt).
Francis Gagné

0
public IEnumerable<Friend> FindFriends()
{
    return userExists ? 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
        }): new List<Friend>();
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.