Подтвердить что ты не робот

LINQ - возвращает ли выражение Where новый экземпляр или ссылку на экземпляр объекта

Это, вероятно, основной вопрос для некоторых, но это влияет на то, как я создаю часть своей программы.

У меня есть одна коллекция типа A:

IEnumerable<A> myCollection;

Я фильтрую свою коллекцию по двум различным критериям:

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

Теперь я знаю, что выражение .Where вернет новый экземпляр IEnumerable, но содержит ли новая коллекция ту же ссылку на экземпляр типа A, ссылки на "myCollection" или созданные новые копии типа A? Если создаются новые экземпляры типа "A", существует ли способ сказать, что "subCollection1" ссылается на те же экземпляры A, что и ссылки "myCollection" ?

Изменить: Добавить дополнительные пояснения.

Я ищу способ, чтобы при изменении экземпляра "A" в "subCollection1" он также был изменен для "myCollection" .

4b9b3361

Ответ 1

Экземпляры одинаковы, если они являются классами, но копируются, если они являются структурами/значениями.

int, byte и double типы значений, как и структуры (например, System.Drawing.Point и самоопределенные структуры). Но строки, все ваши собственные классы, в основном "остальные", ссылочные типы.

Примечание. 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.

Ответ 2

Они - одни и те же объекты. Where только фильтры, Select создает (может создавать) новые экземпляры.

Ответ 3

Собственно, это зависит от коллекции. В некоторых случаях методы 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();

Я не знаю точно, почему он работает таким образом, но это что-то иметь в виду, когда вы пишете свой код:)

может помочь понять Как LINQ работает внутри страны

Ответ 4

Создание нового объекта, являющегося ссылочным типом, является нетривиальным. LINQ не знал бы, как это сделать. LINQ всегда возвращает те же экземпляры при работе со ссылочными типами.

Ответ 5

Я просто хотел добавить к некоторым другим ответам - в общем, когда я не уверен в чем-то, но требую определенного поведения, я добавлю для него unit test. Вы можете легко поставить это в тест, а затем проверить равенство, которое скажет вам, если вы смотрите на ссылку объекта в исходном контейнере. Некоторые могут утверждать, что это глупо, потому что вы "должны просто знать", что происходит, но для меня я знаю, что я либо буду 1) неуверенным, потому что я не удивительный программист, и 2) всегда есть ночи, где мне нужно сжечь полночное масло, и хорошо иметь уверенность в том, что что-то ведет себя так, как вам нужно.