ฉันจะคืนค่า 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
            });
        }

เนื่องจากทุกอย่างอยู่ในแถลงการณ์ส่งคืนฉันจึงไม่รู้ว่าจะทำอย่างไร อยากได้สิ่งนี้ไหม

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
ดูรหัสที่นี่คุณควรใช้ผลตอบแทนและผลตอบแทน
Chris Marisic

คำตอบ:


575

คุณสามารถใช้list ?? Enumerable.Empty<Friend>()หรือมีFindFriendsผลตอบแทนEnumerable.Empty<Friend>()


7
มันจะเปลี่ยนสิ่งต่าง ๆ ไหมถ้าเขากลับมาพูดnew List<Friend>()เพราะมันจะถูกโยนไปIEnumerable<Friend>เมื่อกลับมาจากวิธีการนั้น?
Sarah Vessels

73
new List<Friend>()คือการดำเนินการมีราคาแพงกว่าเพราะมันจะสร้างตัวอย่างของรายการหนึ่ง (และจัดสรรหน่วยความจำสำหรับมันในกระบวนการ)
อิกอร์ Pashchuk


105

สำหรับฉันแล้ววิธีที่งดงามที่สุดคือ yield break


8
แต่นั่นคือถ้าคุณใช้อัตราผลตอบแทนและเช่นนั้นใช่ไหม
Svish

15
+1 เป็นรหัสของเขาอย่างถูกต้องควรใช้ผลตอบแทนสำหรับวิธีที่เขาทำงานกับ IEnumerable
Chris Marisic

6
ให้อภัยความไม่รู้ของฉันเกี่ยวกับเรื่องนี้ แต่คุณช่วยอธิบายวิธีการใช้อัตราผลตอบแทนในบริบทนี้ได้ไหม? ฉันเห็นตัวอย่างในลูปเท่านั้น แต่ไม่ได้วาดภาพที่ชัดเจนสำหรับฉัน
Sergio Tapia

อัปเดตคำตอบด้วยตัวอย่าง เป็นวิธีที่ยอดเยี่ยมที่สุดในการทำสิ่งที่ฉันเห็นด้วย :)
Johny Skovdal

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

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
Enumerable.Empty <T> จะส่งคืนอาร์เรย์ว่างเปล่าของ T (T [0]) โดยมีข้อได้เปรียบที่นำอาร์เรย์ว่างเดิมมาใช้ซ้ำ โปรดทราบว่าวิธีการนี้ไม่เหมาะสำหรับอาร์เรย์ที่ไม่ว่างเนื่องจากองค์ประกอบสามารถแก้ไขได้ (อย่างไรก็ตามไม่สามารถปรับขนาดอาร์เรย์ได้การปรับขนาดเกี่ยวข้องกับการสร้างอินสแตนซ์ใหม่)
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>();
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.