349
votes

Given the following code and the suggestions given in this question, I've decided to modify this original method and ask if there are any values in the IEnumarable return it, if not return an IEnumerable with no values.

Here is the method:

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

Since everything is inside the return statement, I don't know how I could do this. Would something like this work?

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

The above method doesn't work, and in fact it's not supposed to; I just feel it illustrates my intentions. I feel I should specify that the code doesn't work because you can't create an instance of an abstract class.

Here is the calling code, I don't want it to receive a null IEnumerable at any time:

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

        }

Thank you for your time.

6
Looking at the code here you should be using yield return and yield break.Chris Marisic

6 Answers

616
votes

You can use list ?? Enumerable.Empty<Friend>(), or have FindFriends return Enumerable.Empty<Friend>()

174
votes
112
votes

As for me, most elegant way is yield break

8
votes

That's of course only a matter of personal preference, but I'd write this function using yield return:

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
votes

I think the simplest way would be

 return new Friend[0];

The requirements of the return are merely that the method return an object which implements IEnumerable<Friend>. The fact that under different circumstances you return two different kinds of objects is irrelevant, as long as both implement IEnumerable.

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