Làm thế nào tôi có thể trả lại một IEnumerable trống?


328

Đưa ra mã sau đây và các đề xuất được đưa ra trong câu hỏi này , tôi đã quyết định sửa đổi phương thức ban đầu này và hỏi liệu có bất kỳ giá trị nào trong IEnumarable trả về nó không, nếu không trả về IEnumerable không có giá trị.

Đây là phương pháp:

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

Vì mọi thứ đều nằm trong tuyên bố hoàn trả, tôi không biết làm thế nào tôi có thể làm điều này. Có công việc nào như vầy không?

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

Phương pháp trên không hoạt động, và trên thực tế, nó không được phép; Tôi chỉ cảm thấy nó minh họa ý định của tôi. Tôi cảm thấy tôi nên xác định rằng mã không hoạt động vì bạn không thể tạo một thể hiện của một lớp trừu tượng.

Đây là mã gọi, tôi không muốn nó nhận được số IE không có giá trị bất cứ lúc nào:

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

        }

Cảm ơn bạn đã dành thời gian.


2
Nhìn vào mã ở đây, bạn nên sử dụng lợi nhuận và phá vỡ lợi suất.
Chris Marisic

Câu trả lời:


574

Bạn có thể sử dụng list ?? Enumerable.Empty<Friend>(), hoặc có FindFriendstrở lạiEnumerable.Empty<Friend>()


7
Nó sẽ thay đổi mọi thứ nếu anh ta quay trở lại, new List<Friend>()vì nó sẽ được sử dụng IEnumerable<Friend>khi được trả về từ phương thức đó?
Sarah Vessels

73
new List<Friend>()là một hoạt động đắt tiền hơn bởi vì nó sẽ tạo ra một thể hiện của một danh sách (và phân bổ bộ nhớ cho nó trong quá trình này)
Igor Pashchuk


105

Đối với tôi, cách thanh lịch nhất là yield break


8
Nhưng đó là nếu bạn sử dụng lợi nhuận và như vậy, phải không?
Svish

15
+1 là mã của anh ấy một cách chính xác nên sử dụng năng suất cho cách anh ấy làm việc với IEnumerable
Chris Marisic

6
Xin tha thứ cho sự thiếu hiểu biết của tôi về chủ đề này, nhưng bạn có thể vui lòng minh họa cách sử dụng phá vỡ năng suất trong bối cảnh này không? Tôi đã thấy các ví dụ chỉ trong các vòng lặp nhưng điều đó không vẽ ra một bức tranh rõ ràng cho tôi.
Sergio Tapia

Cập nhật câu trả lời với một ví dụ. Thực sự là cách làm thanh lịch nhất tôi sẽ đồng ý. :)
Johny Skovdal

4
Chỉnh sửa đã bị từ chối trong đánh giá ngang hàng, vì vậy đây là ví dụ tôi đã nói về @Pyritie - mặc dù định dạng bị rối, vì vậy tôi cũng đã thêm nó vào 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

Tất nhiên đó chỉ là vấn đề sở thích cá nhân, nhưng tôi sẽ viết hàm này bằng cách sử dụng lợi nhuận:

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

Tôi nghĩ cách đơn giản nhất sẽ là

 return new Friend[0];

Các yêu cầu của trả về chỉ là phương thức trả về một đối tượng thực hiện IEnumerable<Friend>. Thực tế là trong các trường hợp khác nhau, bạn trả lại hai loại đối tượng khác nhau là không liên quan, miễn là cả hai đều thực hiện IEnumerable.


5
Enumerable.Empty <T> thực sự trả về một mảng trống T (T [0]), với lợi thế là cùng một mảng trống được sử dụng lại. Lưu ý rằng phương pháp này không lý tưởng cho các mảng không trống, bởi vì các phần tử có thể được sửa đổi (tuy nhiên một mảng không thể thay đổi kích thước, thay đổi kích thước liên quan đến việc tạo một thể hiện mới).
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>();
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.