Search code examples
c#linqdeep-copy

linq related question


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Comparer.csd
{
    class Program
    {
        /* Confusion is regarding how ToList() method works. Does it do the deep copy or shallow copy??

        /**********OUTPUT
         a a b
         a b c
         a c a
        -----------------
         a a b
         a c a
        -----------------
        1
        2
        3
        OUTPUT ENDS************/

        static void Main(string[] args)
        {
            List<test> list = new List<test>();
            list.Add(new test("a", "b", "c"));
            list.Add(new test("a", "c", "a"));
            list.Add(new test("a", "a", "b"));

            /// sort the list based on first name and last name

            IEnumerable<test> soretedCollection = from t in list
                                     orderby t._fname ascending, t._mname ascending
                                     select t;
            Print(soretedCollection);
            /// remove the first object from the list
            list.RemoveAt(0);
            /// print the list .
            /// Removal of the item from the list is reflected here so I guess sorted collection and list both 
            /// are refering the same data structure
            /// what if I will do 
            /// list = soretedCollection.ToList<test>(); /// is it going to change the reference of the list if some other object 
            /// is holding the reference??
            Print(soretedCollection);

            Dictionary<int, int> dic = new Dictionary<int, int>();            
            dic.Add(1, 1);
            dic.Add(2, 1);
            dic.Add(3, 1);
            List<int> keys = dic.Keys.ToList<int>();
            /// remove the dictionary entry with key=2
            dic.Remove(2);
            /// how come this time it did not remove the second item becuase it is removed from the dictionary.
            for (int i = 0; i < keys.Count; ++i)
            {
                Console.WriteLine(keys[i].ToString());
            }

            Console.Read();
        }

        static void Print(IEnumerable<test> list)
        {
            foreach (test t in list)
            {
                t.Print();
            }
            Console.WriteLine("---------------------");
        }
    }

}

Solution

  • Calling .ToList() forces eager execution of the full enumeration - the result of this is a separate list from the original enumeration, so any changes after .ToList() won't be reflected in that list. The actual items in this list are the same (same object references) as in the original enumeration as @Johannes Rudolph pointed out - so yes that's a shallow copy.

    The IEnumerable<test> though will be lazily executed over the source collection - only when you actively enumerate the items (i.e. by using foreach or .ToList()) will the enumeration create an Enumerator that takes the source collection as it is at that point in time - that means if there are changes in the underlying collection before the Enumerator is created these will be reflected in the enumeration.