Reputation: 3637
private readonly Dictionary<ExcelCellIdentifier, int> allInfoByIdentifier = new Dictionary<ExcelCellIdentifier, int>();
public class ExcelCellIdentifier
{
public ExcelCellIdentifier(string ticker, string identifier)
{
Ticker = ticker;
Identifier = identifier;
}
public string Ticker { get; set; }
public string Identifier { get; set; }
}
Then at some point I would like to search for the int by creating an ExcelCellIdentifier object with the same ticker and identifier, like:
ExcelCellIdentifier ex = new ExcelCellIdentifier("Ticker1", "Identifier1");
int a = allInfoByIdentifier[ex];
//a is a value stored before hand
Is this possible?
Upvotes: 0
Views: 195
Reputation: 127603
Because no one else has given you a proper version using IEquateable here you go
public class ExcelCellIdentifier : IEquatable<ExcelCellIdentifier>
{
public ExcelCellIdentifier(string ticker, string identifier)
{
Ticker = ticker;
Identifier = identifier;
}
public override bool Equals(object obj)
{
var identifier = obj as ExcelCellIdentifier;
if(identifier == null)
return false;
else
return Equals(identifier);
}
public override int GetHashCode()
{
//All this below is a common performance thing I add, if you have the two strings "Foo" and "Bar" it will give you a different hash code than the string "Bar" and "Foo", it gives you a better distribution of the hash.
unchecked
{
int hash = 17;
hash = hash * 23 + Ticker.GetHashCode();
hash = hash * 23 + Identifier.GetHashCode();
return hash;
}
}
public string Ticker { get; set; } //This should likely be changed to {get; private set;}
public string Identifier { get; set; } //This should likely be changed to {get; private set;}
public bool Equals(ExcelCellIdentifier other)
{
return Ticker.Equals(other.Ticker) && Identifier.Equals(other.Identifier);
}
}
Change these two methods to the following to remove case sensitivity to the strings
public override int GetHashCode()
{
//All this below is a common performance thing I add, if you have the two strings "Foo" and "Bar" it will give you a different hash code than the string "Bar" and "Foo", it gives you a better distribution of the hash.
unchecked
{
int hash = 17;
hash = hash * 23 + StringComparer.OrdinalIgnoreCase.GetHashCode(Ticker);
hash = hash * 23 + StringComparer.OrdinalIgnoreCase.GetHashCode(Identifier);
return hash;
}
}
public string Ticker { get; set; } //This should likely be changed to {get; private set;}
public string Identifier { get; set; } //This should likely be changed to {get; private set;}
public bool Equals(ExcelCellIdentifier other)
{
return StringComparer.OrdinalIgnoreCase.Equals(Ticker, other.Ticker) && StringComparer.OrdinalIgnoreCase.Equals(Identifier, other.Identifier);
}
Upvotes: 1
Reputation: 11607
as Damien_The_Unbeliever said, what you need is:
public class myClass
{
private readonly Dictionary<ExcelCellIdentifier, int> allInfoByIdentifier =
new Dictionary<ExcelCellIdentifier, int>(new ExcelCellIdentifier());
public void testIt()
{
allInfoByIdentifier.Add(new ExcelCellIdentifier("Ticker1", "Identifier1"), 4);
ExcelCellIdentifier ex = new ExcelCellIdentifier("Ticker1", "Identifier1");
int a = allInfoByIdentifier[ex];
}
}
public class ExcelCellIdentifier : IEqualityComparer<ExcelCellIdentifier>
{
public ExcelCellIdentifier()
{
}
public ExcelCellIdentifier(string ticker, string identifier)
{
Ticker = ticker;
Identifier = identifier;
}
public string Ticker { get; set; }
public string Identifier { get; set; }
public bool Equals(ExcelCellIdentifier x, ExcelCellIdentifier y)
{
return x.Identifier == y.Identifier &&
x.Ticker == y.Ticker;
}
public int GetHashCode(ExcelCellIdentifier obj)
{
return obj.Identifier.GetHashCode() ^
obj.Ticker.GetHashCode();
}
}
Upvotes: 0
Reputation: 4164
yes, you can do this as long as you either implement IEquatable<ExcelCellIdentifier>
in your ExcelCellIdentifier
class, or instantiate the dictionary with an instance of IEqualityComparer<ExcelCellIdentifier>
.
One important thing to remember is that although I don't think IEquatable<T>
forces you to override GetHashCode()
(even though as commented below it's mandated in the documentation), you need to make sure you override it appropriately, otherwise even if your objects return true for Equals()
, one won't work as a key to find the other in the dictionary.
This is a cause of lots of fun debugging where you're sure your equality comparer is working fine, but somehow your dictionary isn't retrieving anything!
For my money, I prefer to implement a custom equality comparer, which keeps the business of managing your dictionary separate from the implementation of your class:
private readonly Dictionary<ExcelCellIdentifier, int> allInfoByIdentifier =
new Dictionary<ExcelCellIdentifier, int>(new ExcelCellIdentifierComparer());
public class ExcelCellIdentifier
{
private ExcelCellIdentifier(string ticker, string identifier)
{
Ticker = ticker;
Identifier = identifier;
}
public string Ticker { get; set; }
public string Identifier { get; set; }
}
private class ExcelCellIdentifierComparer : IEqualityComparer<ExcelCellIdentifier>
{
public bool Equals(ExcelCellIdentifier x, ExcelCellIdentifier y)
{
return x.Identifier == y.Identifier && x.Ticker == y.Ticker;
}
public int GetHashCode(ExcelCellIdentifier obj)
{
return obj.Identifier.GetHashCode() ^ obj.Ticker.GetHashCode();
}
}
Upvotes: 1
Reputation: 239824
From the documentation:
Dictionary<TKey, TValue>
requires an equality implementation to determine whether keys are equal. You can specify an implementation of theIEqualityComparer<T>
generic interface by using a constructor that accepts a comparer parameter; if you do not specify an implementation, the default generic equality comparerEqualityComparer<T>.Default
is used. If type TKey implements theSystem.IEquatable<T>
generic interface, the default equality comparer uses that implementation.
It's up to you to decide how you want equality to work in this case - either provide a comparer when you construct the dictionary or implement IEquatable<T>
. The middle option doesn't work for you, since the default comparer for reference types uses reference equality.
Upvotes: 3