Reputation: 8630
I've never used Dictionaries before, and I'm just looking to learn more about them.
I'm a bit lost when it comes to Custom Objects. Is it possible to use a custom object like the class below, as the Key, rather than the value?
class Car
{
public Car(int id, string model)
{
ID = id;
Model = model;
}
public int ID { get; private set; }
public string Model { get; private set; }
}
If you where to create a Dictionary, Like this :-
Dictionary<Car, bool> Cars = new Dictionary<Car, bool>();
How would you use the Car object as a Key, when searching the Dictionaries contents?
Upvotes: 1
Views: 3627
Reputation: 2487
var car1 = new Car(1,"A300");
var car2 = new Car(1,"A400");
Adding to a dictionary
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
To get the value you can use
var x=Cars[car1];
Using a key which is not in the dictionary collection will throw an exception.
Upvotes: 1
Reputation: 351
In your situation you are trying to use your custom object as a key in the dictionary, in dictionary data structure each key is unique, so you need to provide a way in your data structure to differentiate one object from other.
This is done by overriding GetHashCode() method, implementing IEquatable is optional but it brings clarity to what you are trying to do.
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();
}
}
Upvotes: 1
Reputation: 1709
You need to implement Equals()
and GetHashCode()
for the Car
type. Since Car is a reference type, you could potentially put a difference instance of the same Car
(Id
property for both Car instances matches, but they point to different objects) in the dictionary and not even be aware.
You don't want this to be possible
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";
for GetHasCode()
, you can return Id.GetHashCode()
for Equals()
, just do the standard boilerplate checks like checking that the types are the same, etc.
This link provides more detail about why you should implement GetHashCode()
Upvotes: 3
Reputation: 720
From 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.
So in your case you need to implement IEquatable<Car>
, for example:
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;
}
}
Upvotes: 2
Reputation: 13696
Yes, this is quite possible, but there's a very important caveat to be aware of.
Dictionaries check keys using default equality comparison. For custom class objects, that means "Is this a reference to the same object". Not "Is this an object with the same data".
So for example:
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
You can resolve this by overriding GetHashValue()
and Equals()
for your class. See here.
Upvotes: 3
Reputation: 203814
To use an object as the key of a Dictionary
it's important for it to have implementations of Equals
and GetHashCode
that properly define what "equality" means for your object.
The default implementations of those two methods is usually not appropriate, as by default they will just compare the references, meaning two different objects with the same values won't be "equal", when you probably want them to be.
Once you have sensible implementations of those methods, you can use the dictionaries indexer to put a Car
instance in, and get the boolean value associated with that Car
.
Upvotes: 2