空のIEnumerableを返すにはどうすればよいですか?


329

次のコードとこの質問の提案を踏まえて、この元のメソッドを変更し、IEnumarableに値があるかどうかを確認し、値がない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
            });
        }

すべてがreturnステートメントの中にあるので、どうすればよいのかわかりません。このようなものでしょうか?

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

上記の方法は機能せず、実際には機能しません。それは私の意図を説明しているだけだと思います。抽象クラスのインスタンスを作成できないため、コードが機能しないことを指定する必要があると思います。

ここに呼び出しコードがありますが、いつでもnull 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
ここのコードを見ると、yield returnとyield breakを使用しているはずです。
Chris Marisic 2010

回答:


575

を使用するlist ?? Enumerable.Empty<Friend>()か、FindFriends返品することができますEnumerable.Empty<Friend>()


7
たとえば、そのメソッドから返されnew List<Friend>()IEnumerable<Friend>ときにキャストされるので、彼が戻った場合、それは状況を変えるでしょうか?
サラ船

73
new List<Friend>()リストのインスタンスを作成する(そしてプロセスにメモリを割り当てる)ため、よりコストのかかる操作です
Igor Pashchuk


105

私にとって、最もエレガントな方法は yield break


8
しかし、それはあなたが利回りのリターンなどを使用する場合ですよね?
Svish

15
+1は、彼のコードがIEnumerableでの作業方法に利回りを正しく使用する必要があるため+1
Chris Marisic 2010

6
この件に関する私の無知を許してください。しかし、この文脈での利回りブレイクの使い方を説明していただけませんか?forループでのみ例を見てきましたが、それは私には明確な絵を描きません。
セルジオタピア

例を使用して回答を更新しました。私が同意する最もエレガントな方法です。:)
ジョニー・スコブダル2015

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; } }
ジョニーSkovdal

8

もちろん、これは個人的な好みの問題ですが、この関数は、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

最も簡単な方法は

 return new Friend[0];

戻りの要件は、メソッドが実装するオブジェクトを返すことだけですIEnumerable<Friend>。異なる状況で2つの異なる種類のオブジェクトを返すという事実は、両方がIEnumerableを実装している限り、無関係です。


5
Enumerable.Empty <T>は実際にはT(T [0])の空の配列を返し、同じ空の配列が再利用されるという利点があります。要素は変更できるため、この方法は空でない配列には理想的ではないことに注意してください(ただし、配列のサイズを変更することはできません。サイズ変更には新しいインスタンスの作成が含まれます)。
FrancisGagné10年

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>();
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.