1

我以前从未使用过字典,我只是想了解更多关于它们的信息。

当谈到自定义对象时,我有点迷茫。是否可以使用像下面的类这样的自定义对象作为键,而不是值?

class Car
    {
        public Car(int id, string model)
        {
            ID = id;
            Model = model;
        }

        public int ID { get; private set; }
        public string Model { get; private set; }
    }

如果你在哪里创建字典,像这样:-

 Dictionary<Car, bool> Cars = new Dictionary<Car, bool>();

在搜索字典内容时,您将如何使用 Car 对象作为键?

4

6 回答 6

3

是的,这很有可能,但有一个非常重要的警告需要注意。

字典使用默认相等比较检查键。对于自定义类对象,这意味着“这是对同一对象的引用”。不是“这是一个具有相同数据的对象吗”。

例如:

var car1 = new Car(1, "Avalon");
var car2 = car1;
var car3 = new Car(1, "Avalon");

Cars.Add(car1, true);
Console.WriteLine(Cars[car2]); // writes "True";
Console.WriteLine(Cars[car3]); // throws a KeyNotFoundException

您可以通过覆盖GetHashValue()Equals()为您的班级解决此问题。见这里

于 2013-02-26T16:41:17.330 回答
3

您需要为类型实现Equals()和。由于 Car 是一种引用类型,您可能会在字典中放置相同的差异实例(两个 Car 实例的属性匹配,但它们指向不同的对象),甚至不知道。GetHashCode()CarCarId

你不希望这成为可能

var carMap = new Dictionary<Car, string>();

var carOne = new Car { Id = 1 };
var careTwo = new Car { Id = 1 };

carMap[carOne] = "one";

// you want this line to fail since a Car with this Id is already present
carMap[carTwo] = "two";

因为GetHasCode(),你可以返回Id.GetHashCode()

对于Equals(),只需进行标准样板检查,例如检查类型是否相同等。

此链接提供了有关您应该实施的原因的更多详细信息GetHashCode()

于 2013-02-26T16:41:59.473 回答
2

要将对象用作 a 的键,Dictionary重要的是它具有实现EqualsGetHashCode正确定义“平等”对您的对象意味着什么。

这两种方法的默认实现通常是不合适的,因为默认情况下它们只会比较引用,这意味着具有相同值的两个不同对象不会“相等”,而您可能希望它们相同。

一旦你对这些方法有了合理的实现,你就可以使用字典索引器来放置一个Car实例,并获取与它关联的布尔值Car

于 2013-02-26T16:41:02.100 回答
2

来自 MSDN:(http://msdn.microsoft.com/en-us/library/xfhwa508 (v=vs.80).aspx )

If type TKey implements the System.IEquatable generic interface, the default equality comparer uses that implementation.

因此,在您的情况下,您需要实施IEquatable<Car>,例如:

   class Car : IEquatable<Car>
    {
        public Car(int id, string model)
        {
            ID = id;
            Model = model;
        }

        public int ID { get; private set; }
        public string Model { get; private set; }

        public bool Equals(Car other)
        {
            return this.ID == other.ID;
        }
    }
于 2013-02-26T16:44:17.847 回答
1

在您的情况下,您尝试将自定义对象用作字典中的键,在字典数据结构中,每个键都是唯一的,因此您需要在数据结构中提供一种方法来区分一个对象与另一个对象。

这是通过覆盖 GetHashCode() 方法来完成的,实现 IEquatable 是可选的,但它使您尝试做的事情变得清晰。

class Car : IEquatable<Car>
    {
        public Car(int id, string model)
        {
            ID = id;
            Model = model;
        }

        public int ID { get; private set; }
        public string Model { get; private set; }

        public bool Equals(Car other)
        {
            return !ReferenceEquals(null, other) && ID == other.ID;
        }
// This is a must if you like to correctly use your object as a key in dictionary
        public override int GetHashCode()
        {
            return ID.GetHashCode();
        }
    }
于 2013-02-26T16:48:21.917 回答
1
var car1 = new Car(1,"A300");
var car2 = new Car(1,"A400");

添加到字典

   Cars.Add(car1 ,true);
   Cars.Add(car2 ,true);
   Cars.ContainsKey(car1) - //which returns boolean can be used to check for the exisitence of a key

要获得您可以使用的价值

   var x=Cars[car1];

使用不在字典集合中的键将引发异常。

于 2013-02-26T16:43:34.117 回答