2

Casting does not make copies of objects. More concretely IEnumerable.Cast, according to this resource, which makes total sense. However for this app, find fiddle, reference equals is false if I change the log at the end from the Cast<BaseClass> to Cast<DerivedClass1>. Check logs at the main program.

are equal: True areEqualRef: True areEqualRef: False

Posting the code, just in case, omit it of you get my point playing around with the fiddle :)

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

namespace ConsoleApp17
{
    public class BaseClass {
        string name = "I am base";
        public Type type;
        public enum Type { 
            a,b,c,d
        }
        public BaseClass(Type type) {
            this.type = type;
        }
    }

    public class DerivedClass1 : BaseClass
    {
        string name = "I am derivedA";

        public DerivedClass1(): base(Type.a) {
        
        }
    }


    public class DerivedClass2 : BaseClass
    {
        string name = "I am derivedB";
        public DerivedClass2() : base(Type.b)
        {

        }
    }

    public class Foo
    {
        public Dictionary<BaseClass.Type, List<BaseClass>> dict = new Dictionary<BaseClass.Type, List<BaseClass>>();

        public Foo() {

            dict[BaseClass.Type.a] = new List<BaseClass>();
            dict[BaseClass.Type.b] = new List<BaseClass>();
            dict[BaseClass.Type.c] = new List<BaseClass>();
            dict[BaseClass.Type.d] = new List<BaseClass>();

            AddItem(new DerivedClass1());
            AddItem(new DerivedClass1());

            AddItem(new DerivedClass2());
            AddItem(new DerivedClass2());
            AddItem(new DerivedClass2());
        }

        public IEnumerable<T> GetEnumByType<T>(BaseClass.Type type) where T : BaseClass
        {
            if (dict.ContainsKey(type))
            {
                if (type == BaseClass.Type.a)
                {
                    Console.WriteLine($"are equal:  { object.ReferenceEquals(dict[type].Cast<T>(), dict[BaseClass.Type.a])}");
                }

                return dict[type].Cast<T>();
            }
            return null;
        }

        public void AddItem<T>(T item) where T : BaseClass
        {
            dict[item.type].Add(item);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Foo foo = new Foo();
            IEnumerable myList = foo.GetEnumByType<BaseClass>(BaseClass.Type.a);

            Console.WriteLine($"areEqualRef: {object.ReferenceEquals(foo.dict[BaseClass.Type.a].Cast<BaseClass>(), foo.dict[BaseClass.Type.a])}");
            Console.ReadLine();
        }
    }
}

Update: Updated the fiddle with both logs to avoid the need of copy/pasting

rustyBucketBay
  • 4,320
  • 3
  • 17
  • 47

1 Answers1

3

You need to notionally separate what is being compared here. When it says that Enumerable.Cast<T> doesn't make copies of objects, it is talking about the individual objects in the sequence. Not the sequence itself. In order to perform the necessary reshaping, the sequence returned from the Cast<T> method is a different wrapper/decorator instance over the original sequence.

Since you're using ReferenceEquals on the sequence, this will report false. However, if you were to compare each object from the sequences (pairwise in turn), you would find that those were the same objects.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Thanks for your answer, i was not aware of that. And is there a builtin way to check if a collection is passed around by many classes in a big app, if actually none of their elements inside has changed reference? (meaning without self implementation looping through the two sequence refs comparing all the elements) – rustyBucketBay Dec 28 '21 at 11:02
  • I mean to find out if both collections point to the same sequence object – rustyBucketBay Dec 28 '21 at 11:03
  • @rustyBucketBay the SequenceEqual method comes close, but you'd need to supply a custom comparer that uses referenceequals – Marc Gravell Dec 28 '21 at 11:54