LINQ - Where表达式是否返回对象实例的新实例或引用

时间:2010-08-27 12:38:59

标签: c# .net linq

对于某些人来说,这可能是一个基本问题,但它会影响我设计一个程序的方式。

我有一个类型为A的集合:

IEnumerable<A> myCollection;

我按照两个不同的标准过滤我的收藏:

IEnumerable<A> subCollection1 = myCollection.Where(x => x.Count > 10);
etc.

现在,我知道.Where表达式将返回IEnumerable的新实例,但是新集合是否包含对'myCollection'引用的类型A实例的相同引用,或者是否创建了类型A的新副本?如果创建了类型为“A”的新实例,是否可以说“subCollection1”引用与“myCollection”引用相同的A实例?

编辑:添加进一步说明。

我正在寻找一种方法,以便当我对'subCollection1'中的'A'实例进行更改时,它也会针对'myCollection'进行修改。

5 个答案:

答案 0 :(得分:42)

如果它们是类,则实例相同,但如果它们是结构/值类型则复制。

int,byte和double是value types,结构(如System.Drawing.Point和自定义结构)也是如此。 但是字符串,你自己的所有类,基本上都是“其余的”,都是reference types

注意:LINQ使用与所有其他任务相同的规则。

对象:

Person p1 = new Person();
p1.Name = "Mr Jones";
Person p2 = p1;
p2.Name = "Mr Anderssen";
// Now p1.Name is also "Mr Anderssen"

结构:

Point p1 = new Point();
p1.x = 5;
Point p2 = p1;
p2.x = 10;
// p1.x is still 5

使用LINQ时适用相同的规则。

答案 1 :(得分:12)

实际上这取决于收藏品。在某些情况下,Linq方法可以返回克隆对象而不是对原始文件的引用,请看一下这个测试:

        [Test]
    public void Test_weird_linq()
    {
        var names = new[]{"Fred", "Roman"};
        var list = names.Select(x => new MyClass() { Name = x });

        list.First().Name = "Craig";
        Assert.AreEqual("Craig", list.First().Name);            
    }

    public class MyClass
    {
        public string Name { get; set; }
    }

即使很多人认为在“list.First()”中会返回相同的对象,但是这个测试会失败,但是如果你使用“用ToList()修改的另一个集合”,它将会起作用

var list = names.Select(x => new MyClass() { Name = x }).ToList();

我不知道为什么它会以这种方式工作,但是在编写代码时需要注意的事项:)

有助于理解How LINQ works internally

答案 2 :(得分:9)

它们是相同的对象。 Where仅过滤,Select生成(可生成)新实例。

答案 3 :(得分:1)

制作一个作为参考类型的新对象并非易事。 LINQ不知道该怎么做。在处理引用类型时,LINQ总是返回相同的实例。

答案 4 :(得分:0)

我只想添加其他一些答案 - 一般来说,当我不确定某些东西但需要特定行为时,我会为它添加一个单元测试。您可以轻松地将其置于测试中,然后检查是否相等,这将告诉您是否正在查看原始容器中对象的引用。有些人可能认为这是愚蠢的,因为你“应该只知道”会发生什么,但对我来说,我知道我要么1)不确定,因为我不是一个很棒的程序员,2)总是有我需要燃烧的夜晚午夜的油,最好让人放心,你需要的东西就像你需要的那样。