简体   繁体   中英

C# ContainsKey returns true once an item is in the Collection

I am pretty sure that my problem comes from a really stupid mistake but I can not find it...

I am using a custom class as the key in a SortedList(I also tried SortedDictionary). The first item gets added without a problem but when I try to add a second Item ContainsKey() returns true.

The Class I am using as a Key overrrides Equals() and GetHashCode(). I checked what items actually get compared and that's what I found out: Manually calling Equals() to compare two items works just fine but when it gets called via ContainsKey the object compares itself with the same or another instance of itself. I made sure to check if the object to be added is indeed a new one and it is...

This is the Key-Class

using System;
using System.Collections;
using System.Collections.Generic;
using TFVR.Components.Gaia.Content.Element;
using UnityEngine;

namespace TFVR.Components.Gaia.Content.QueueUi
{
    public class QueueEntryElement : IComparable
    {
        public string Created;
        public string ProductId;
        public ContactInformationElement ContactInformation;
        public int Priority;
        public string OrderId;

        public QueueEntryElement(string created, string productId
            , ContactInformationElement contactInformation, int priority
            , string orderId)
        {
            Created = created;
            ProductId = productId;
            ContactInformation = contactInformation;
            Priority = priority;
            OrderId = orderId;
        }

        public int CompareTo(object obj)
        {
            if (obj == null) return 1;

            QueueEntryElement otherQueueEntryElement = obj as QueueEntryElement;
            if (otherQueueEntryElement != null)
                return this.Priority.CompareTo(otherQueueEntryElement.Priority);
            else
                throw new ArgumentException("Object is not a QueueEntryElement");
        }
        public override bool Equals(object obj)
        {
            if ((obj == null) || !this.GetType().Equals(obj.GetType()))
            {
                return false;
            }
            else
            {
                QueueEntryElement e = (QueueEntryElement)obj;
                return (this.OrderId == e.OrderId);
            }
        }
        public override int GetHashCode()
        {
            return OrderId.GetHashCode();
        }
        public override string ToString()
        {
            string str = "Created: "
                + Created + ", "
                + "Product Id: "
                + ProductId + ", "
                + "Contact Information: "
                + "{" + ContactInformation + "}" + ", "
                + "Priority: "
                + Priority + ", "
                + "Order Id: "
                + OrderId;
            return str;
        }
    }
}

This is the code where I am trying to add to the SortedList

SortedList<QueueEntryElement, string> dict = new SortedList<QueueEntryElement, string>();
private void add(QueueEntryElement q, string 
{
        if (!dict.ContainsKey(q))
        {
            dict.Add(q, s);
        }
}

ContactInformationElement c1 = new ContactInformationElement("a","b","c","d","e");
QueueEntryElement e1 = new QueueEntryElement("a","b", c1, 0,"123");

ContactInformationElement c2 = new ContactInformationElement("f", "g", "h", "i", "j");
QueueEntryElement e2 = new QueueEntryElement("c", "d", c2, 0, "234");

add(e1,"one");
add(e2,"two");

The problem here is that SortedList.ContainsKey uses CompareTo... NOT Equals to determine existence.

This means that you are basically using Priority as the Key NOT OrderId.

So for the purpose of your example the actual key is Priority.

So if your items do not have unique priority values then they will not be added to the "dictionary".

This is the normal behavior of the C# Generic SortedList.

I added some dummy code just in case anyone is still interested in testing. To solve my problem i simply changed my CompareTo() to this:

public int CompareTo(QueueEntryElement obj)
        {
            if (obj == null) return 1;
            QueueEntryElement otherQueueEntryElement = obj as QueueEntryElement;
            if (otherQueueEntryElement != null)
            {
                if (Priority.CompareTo(otherQueueEntryElement.Priority) == 0)
                {
                    return OrderId.CompareTo(otherQueueEntryElement.OrderId);
                }
                return 0;
            }
            else
                throw new ArgumentException("Object is not a QueueEntryElement");
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM