首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么LINQ对待两个做“相同”事情的方法是不同的?

为什么LINQ对待两个做“相同”事情的方法是不同的?
EN

Stack Overflow用户
提问于 2009-06-24 03:35:30
回答 4查看 189关注 0票数 2

我今天遇到了一个有趣的问题,我有两个方法,快速浏览一下,它们都做了同样的事情。即返回Foo对象IEnumerable。

下面我将它们定义为List1和List2:

代码语言:javascript
复制
public class Foo
{
    public int ID { get; set; }
    public bool Enabled { get; set;}    
}

public static class Data
{
    public static IEnumerable<Foo> List1
    {
        get
        {
            return new List<Foo>
            {
                new Foo {ID = 1, Enabled = true},
                new Foo {ID = 2, Enabled = true},
                new Foo {ID = 3, Enabled = true}
            };
        }
    }

    public static IEnumerable<Foo> List2
    {
        get
        {
            yield return new Foo {ID = 1, Enabled = true};
            yield return new Foo {ID = 2, Enabled = true};
            yield return new Foo {ID = 3, Enabled = true};
        }
    }
}

现在考虑以下测试:

代码语言:javascript
复制
IEnumerable<Foo> listOne = Data.List1;
listOne.Where(item => item.ID.Equals(2)).First().Enabled = false;
Assert.AreEqual(false, listOne.ElementAt(1).Enabled);
Assert.AreEqual(false, listOne.ToList()[1].Enabled);  

IEnumerable<Foo> listTwo = Data.List2;
listTwo.Where(item => item.ID.Equals(2)).First().Enabled = false;
Assert.AreEqual(false, listTwo.ElementAt(1).Enabled);
Assert.AreEqual(false, listTwo.ToList()[1].Enabled);  

这两种方法似乎做了“相同”的事情。

为什么测试代码中的第二个断言会失败?

为什么listTwo的第二个"Foo“项在listOne中时没有被设置为false?

注意:我想要解释一下为什么会发生这种情况,以及两者之间的区别。不知道如何修复第二个断言,因为我知道如果我向List2添加一个ToList调用,它就会工作。

EN

Stack Overflow用户

发布于 2009-06-24 04:24:02

这绝对不是一回事。

第一个方法在你调用它的时候构建并返回一个列表,如果你想要的话,你可以把它转换回list和list-y元素,包括添加或删除项,一旦你把结果放入一个变量中,你就可以对这一组结果进行操作。调用该函数会产生另一组结果,但重用单个调用的结果会对相同的对象起作用。

第二个是构建一个IEnumerable。您可以枚举它,但如果不先对其调用.ToList(),就不能将其视为列表。实际上,在实际迭代该方法之前,调用该方法不会做任何事情。考虑一下:

代码语言:javascript
复制
var fooList = Data.List2().Where(f => f.ID > 1);
// NO foo objects have been created yet.
foreach (var foo in fooList)
{
   // a new Foo object is created, but NOT until it's actually used here
   Console.WriteLine(foo.Enabled.ToString());  
}

注意,上面的代码将创建第一个(未使用的) Foo实例,但直到进入foreach循环。因此,直到被调用时,这些项才会被实际创建。但这意味着每次调用它们时,您都在构建一组新的项。

票数 2
EN
查看全部 4 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1036272

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档