C#字典-自定义对象

本文关键字:对象 自定义 字典 | 更新日期: 2023-09-27 18:01:18

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

当谈到自定义对象时,我有点不知所措。是否可以使用类似下面类的自定义对象作为键,而不是值?

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

在搜索Dictionaries内容时,您将如何使用Car对象作为密钥?

C#字典-自定义对象

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

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

例如:

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()来解决此问题。请参见此处。

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

你不希望这是可能的

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() 的更多详细信息

要将对象用作Dictionary的键,EqualsGetHashCode的实现必须正确定义"相等"对对象的含义。

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

一旦有了这些方法的合理实现,就可以使用字典索引器将Car实例放入,并获得与该Car关联的布尔值。

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

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

这是通过重写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();
        }
    }
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];

使用字典集合中没有的键将引发异常。