Як я можу повернути порожній IEumerable?


329

Враховуючи наведений нижче код та пропозиції, наведені в цьому запитанні , я вирішив змінити цей початковий метод і запитати, чи є якісь значення в IEnumerable повернути його, якщо не повернути IEnumerable без значень.

Ось метод:

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

Оскільки все знаходиться у зворотній заяві, я не знаю, як я міг це зробити. Чи щось подібне буде працювати?

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

Вищеописаний метод не працює, і насправді цього не передбачається; Я просто відчуваю, що це ілюструє мої наміри. Я вважаю, що слід зазначити, що код не працює, оскільки ви не можете створити екземпляр абстрактного класу.

Ось код виклику, я не хочу, щоб він отримував нульовий IEnumerable будь-коли:

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

        }

Спасибі за ваш час.


2
Дивлячись на код тут, ви повинні використовувати прибуток і перерву врожайності.
Кріс Марісіч

Відповіді:


575

Ви можете використовувати list ?? Enumerable.Empty<Friend>()або FindFriendsповернутиEnumerable.Empty<Friend>()


7
Чи це змінить речі, якщо він повернеться, скажімо, new List<Friend>()оскільки це буде передано, IEnumerable<Friend>коли він повернеться з цього методу?
Сара Везлес

73
new List<Friend>()це більш дорога операція, оскільки вона створить екземпляр списку (і виділить йому пам’ять у процесі)
Ігор Пащук


105

Як на мене, найелегантніший спосіб yield break


8
Але це якщо ви використовуєте прибуток і таке, чи не так?
Свиш

15
+1, оскільки його код повинен правильно використовувати урожай для того, як він працює з IEnumerable
Chris Marisic

6
Вибачте моє незнання з цього приводу, але ви можете, будь ласка, проілюструвати, як використовувати перерву в цьому контексті? Я бачив приклади лише для циклів, але це не малює для мене чіткої картини.
Серхіо Тапія

Оновіть відповідь прикладом. Дійсно, це найелегантніший спосіб зробити це, я погодився б. :)
Джонні Сковдал

4
Редагування було відхилено в експертній оцінці, ось ось приклад, про який я говорив @Pyritie - форматування все ж заплуталося, тому я також додав його до pastebin.com/X9Z49Vq1 :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; } }
Джонні Сковдал

8

Звичайно, це лише питання особистої переваги, але я б написав цю функцію, використовуючи віддачу прибутковості:

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

Я думаю, що найпростішим був би спосіб

 return new Friend[0];

Вимоги повернення полягають лише в тому, що метод повертає об'єкт, який реалізується IEnumerable<Friend>. Той факт, що за різних обставин ви повертаєте два різні види об’єктів, не має значення, якщо обидва реалізують IEnumerable.


5
Численні. Порожній <T> фактично повертає порожній масив T (T [0]), з тим перевагою, що той самий порожній масив використовується повторно. Зауважте, що цей підхід не є ідеальним для не порожніх масивів, оскільки елементи можуть бути змінені (однак масив не може бути змінено, зміна розміру передбачає створення нового екземпляра).
Френсіс Ганьє

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>();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.