【问题标题】:ReferenceEquals with casting challenge. Casting to child type make ReferenceEquals return falseReferenceEquals 与铸造挑战。转换为子类型使 ReferenceEquals 返回 false
【发布时间】:2021-12-28 10:39:43
【问题描述】:

铸造不会复制对象。更具体地说,IEnumerable.Cast,根据this 资源,这完全有道理。但是对于这个应用程序,找到fiddle,如果我将最后的日志从Cast<BaseClass> 更改为Cast<DerivedClass1>,则引用等于是错误的。在主程序中查看日志。

are equal: True areEqualRef: True areEqualRef: False

发布代码,以防万一,省略它,让我的意思是玩弄小提琴:)

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();
        }
    }
}

更新: 更新了两个日志的小提琴以避免复制/粘贴的需要

【问题讨论】:

    标签: c# reference equality


    【解决方案1】:

    您需要在概念上区分这里要比较的内容。当它说Enumerable.Cast&lt;T&gt; 不复制对象时,它是在谈论序列中的单个对象。不是序列本身。为了执行必要的整形,Cast&lt;T&gt; 方法返回的序列是与原始序列不同的包装器/装饰器实例。

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

    【讨论】:

    • 感谢您的回答,我不知道这一点。是否有一种内置方法来检查一个集合是否被大型应用程序中的许多类传递,如果实际上它们内部的元素都没有改变引用? (意味着没有自我实现循环通过比较所有元素的两个序列参考)
    • 我的意思是找出两个集合是否指向同一个序列对象
    • @rustyBucketBay SequenceEqual 方法很接近,但您需要提供一个使用 referenceequals 的自定义比较器
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-10
    • 2011-05-19
    相关资源
    最近更新 更多