用一行代码填充Enumerable.ToList

时间:2017-06-05 12:22:41

标签: c# .net ienumerable

请参阅以下人员类:

public class Person
    {
        int _id { get; set; }
        string _name { get; set; }

        public Person (int id, string name)
        {
            _id = id;
            _name = name;
        }

        public Person()
        {
        }

        public IEnumerable<Person> GetPeople()
        {
            _id = 1;
            _name = "James";
            yield return this;

            _id = 2;
            _name = "Michael";
            yield return this;

            _id = 3;
            _name = "Sarah";
            yield return this;
        }
    }

以及下面的客户端代码:

Person p1 = new Person();
IEnumerable<Person> personEnumerable = p1.GetPeople();
List<Person> personList = personEnumerable.ToList();

为什么PersonList在运行之后包含Sarah的三个条目?在客户端中填充personList的最佳方法是什么?

2 个答案:

答案 0 :(得分:6)

因为GetPeople不创建新实例,但修改当前实例并返回3次。

以下代码生成预期结果:

    public static IEnumerable<Person> GetPeople()
    {
        yield return new Person(1, "James");
        yield return new Person(2, "Michael");
        yield return new Person(3, "Sarah");
    }

答案 1 :(得分:3)

你应该看到这种行为,对吧?

var p1 = new Person(1, "Tom");
var p2 = p1;
p2._id = 2;
// now p1._id is 2 as well!

这正是这里发生的事情。在第一个return this之后,再次使用ID 2修改this并命名为Michael。这会导致返回的this也会更改,因为它们引用同一个对象。您从未使用new创建新对象。第三次收益率回报也是如此。

要解决此问题,只需将Person更改为结构(因此它现在是值类型),或者在JanDotNet的答案中实现该方法。