C# ContainsKey возвращает true, когда элемент находится в коллекции - PullRequest
3 голосов
/ 22 января 2020

Я почти уверен, что моя проблема возникла из-за действительно глупой ошибки, но я не могу ее найти ...

Я использую пользовательский класс в качестве ключа в SortedList (я также пробовал SortedDictionary). Первый элемент добавляется без проблем, но при попытке добавить второй Item ContainsKey () возвращает true.

Класс, который я использую в качестве ключа, переопределяет Equals () и GetHashCode (). Я проверил, какие элементы на самом деле сравниваются, и вот что я обнаружил: ручной вызов Equals () для сравнения двух элементов прекрасно работает, но когда он вызывается через ContainsKey, объект сравнивает себя с тем же или другим экземпляром самого себя. Я проверил, действительно ли добавляемый объект является новым, и он ...

Это класс ключей

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

Это код, где я нахожусь пытается добавить в 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");

Ответы [ 2 ]

3 голосов
/ 23 января 2020

Проблема здесь в том, что SortedList.ContainsKey использует CompareTo ... NOT Equals для определения существования.

Это означает, что вы в основном используете Priority в качестве ключа NOT OrderId.

Так что для цель вашего примера - фактический ключ: Приоритет.

Таким образом, если ваши элементы не имеют уникальных значений приоритета, они не будут добавлены в «словарь».

Это нормальное поведение C# Generi c SortedList.

0 голосов
/ 24 января 2020

Я добавил некоторый фиктивный код на тот случай, если кто-то все еще заинтересован в тестировании. Чтобы решить мою проблему, я просто изменил свой CompareTo () на это:

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");
        }
...