ReferenceEquals 铸造挑战。转换为子类型使 ReferenceEquals return false

ReferenceEquals with casting challenge. Casting to child type make ReferenceEquals return false

转换不复制对象。更具体地说 IEnumerable.Cast, according to this resource, which makes total sense. However for this app, find fiddle,如果我将末尾的日志从 Cast<BaseClass> 更改为 Cast<DerivedClass1>,引用等于是假的。检查主程序的日志。

are equal: True areEqualRef: True areEqualRef: False

发布代码,以防万一,如果你明白我的意思,请忽略它 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();
        }
    }
}

更新: 用两个日志更新 fiddle 以避免需要 copy/pasting

您需要在概念上将此处比较的内容分开。当它说 Enumerable.Cast<T> 不复制对象时,它指的是序列 中的单个对象 。不是序列本身。为了执行必要的重塑,从 Cast<T> 方法返回的序列与原始序列不同 wrapper/decorator 实例。

由于您在序列上使用ReferenceEquals,这将报告false。但是,如果您要比较序列中的每个对象(依次成对),您会发现那些是相同的对象。