Boş bir IEnumerable'ı nasıl iade edebilirim?


329

Aşağıdaki kod ve bu soruda verilen öneriler göz önüne alındığında, bu özgün yöntemi değiştirmeye karar verdim ve IEnumarable herhangi bir değer olup olmadığını sormak, değer içermeyen bir IEnumerable döndürmez.

İşte yöntem:

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

Her şey dönüş ifadesinin içinde olduğundan, bunu nasıl yapabileceğimi bilmiyorum. Bunun gibi bir şey olur mu?

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

Yukarıdaki yöntem işe yaramıyor ve aslında olması gerekmiyor; Sadece niyetlerimi gösterdiğini hissediyorum. Soyut bir sınıf örneği oluşturamazsınız çünkü kod çalışmıyor belirtmek gerektiğini hissediyorum.

İşte arama kodu, herhangi bir zamanda boş bir IEnumerable almak istemiyorum:

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

        }

Zaman ayırdığın için teşekkürler.


2
Buradaki koda bakarak verim getirisi ve verim kırılması kullanıyor olmalısınız.
Chris Marisic

Yanıtlar:


575

Kullanabilir list ?? Enumerable.Empty<Friend>()veya FindFriendsiade edebilirsinizEnumerable.Empty<Friend>()


7
Diyelim ki, o yöntemden döndüğünde new List<Friend>()uygulanacağı için IEnumerable<Friend>geri dönerse bir şeyleri değiştirir mi ?
Sarah Vessels

73
new List<Friend>()daha pahalı bir işlemdir çünkü bir liste örneği oluşturur (ve bu süreçte bellek ayırır)
Igor Pashchuk


105

Bana gelince, en zarif yol yield break


8
Ama bu getiri getirisi kullanırsanız öyle değil mi?
Svish

15
+ 1 kodu doğru olarak IEnumerable ile çalışma şekli için verimi kullanmalıdır
Chris Marisic

6
Konu hakkındaki cehaletimi affedin, ama lütfen bu bağlamda verim kırılmasının nasıl kullanıldığını gösterebilir misiniz? Sadece döngüler için örnekler gördüm ama bu benim için net bir resim çizmiyor.
Sergio Tapia

Cevabı bir örnekle güncelledi. Gerçekten bunu yapmanın en zarif yolu kabul ediyorum. :)
Johny Skovdal

4
Düzenleme akran incelemesinde reddedildi, bu yüzden @Pyritie hakkında konuştuğum örnek - biçimlendirme yine de dağınık, bu yüzden bunu pastebin.com/X9Z49Vq1'e ekledim :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

Bu elbette sadece kişisel bir tercih meselesidir, ancak bu işlevi getiri dönüşü kullanarak yazardım:

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

Bence en basit yol

 return new Friend[0];

Geri dönüşün gereksinimleri sadece yöntemin uygulayan bir nesneyi döndürmesidir IEnumerable<Friend>. Farklı koşullar altında, her ikisi de IEnumerable uyguladığı sürece, iki farklı nesne türünü geri döndürmeniz önemsizdir.


5
Boş <T> aslında aynı boş dizinin yeniden kullanılması avantajıyla boş bir T (T [0]) dizisi döndürür. Bu yaklaşımın boş olmayan diziler için ideal olmadığını unutmayın, çünkü öğeler değiştirilebilir (ancak bir dizi yeniden boyutlandırılamaz, yeniden boyutlandırma yeni bir örnek oluşturmayı içerir).
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>();
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.