Dictionary <TKey, TValue> I believe everyone has used it. But what if the Dictionary key is a TKey array (or IList <TKey>?
This is the case to be discussed today: MultiKeyDictionary <TKey, TValue>
Let's take a look at the counterexample: Public class MultiKeyDictionary <TKey, TValue>: IDictionary <TKey [], TValue>
{
Private static readonly List <Type> COLUMNTYPELIST;
Private const string HASHCODECOLNAME = "HASHCODE ";
Private const string KEYCOLMNFORMAT = "KEY {0 }";
Private const int MAXPRIMARYKEYCOUNT = 0x1f;
Private int _ keyCount;
Private able _ DataTable;
Private TKey _ defaultKeyValue;
Private Dictionary <string, TValue> _ hashTable;
Private MultiKeyDictionary ()
{
This. _ keyCount = 0;
This. _ dataTable = null;
This. _ hashTable = null;
This. _ defakeykeyvalue = default (TKey );
If (! MultiKeyDictionary <TKey, TValue>. COLUMNTYPELIST. Contains (typeof (TKey )))
{
Throw new ArgumentException ("", typeof (TKey). Name ));
}
}
Public MultiKeyDictionary (int keyCount, TKey defaultKeyValue): this ()
{
If (keyCount <= 0)
{
Throw new ArgumentOutOfRangeException ("keyCount ");
}
If (defakeykeyvalue = null)
{
Throw new ArgumentNullException ("defaultKeyValue ");
}
This. _ keyCount = keyCount;
This. _ dataTable = this. CreateDataTable ();
This. _ hashTable = new Dictionary <string, TKey> ();
This. _ defakeykeyvalue = defakeykeyvalue;
}
Public void Add (TKey [] keyList, TValue value)
{
If (keyList = null) | (keyList. Length> this. _ keyCount ))? 1: 0 )! = 0)
{
Throw new ArgumentOutOfRangeException ("keyList ");
}
If (this. ContainsKey (aoKeyList ))
{
Throw new ArgumentException ("");
}
DataRow dr = this. _ dataTable. NewRow ();
For (int I = 0; I <this. _ keyCount; I ++)
{
TKey key = default (TKey );
TKey value = key;
If (I <keyList. Length)
{
Value = keyList [I];
}
Else
{
Value = this. _ defaultKeyValue;
}
Dr [I] = value;
}
String hashCode = Guid. NewGuid (). ToString ();
Dr ["HASHCODE"] = hashCode;
This. _ dataTable. Rows. Add (dr );
This. _ hashTable. Add (hashCode, value );
}
// Save 600 lines of code
}
The first time I saw this code, I was dumpfounded. I didn't expect this code to be written like this. It uses a able to put multiple key values, and it specifies that each column above is the primary key, to the last
Column, put a Guid ToString, and then use Dictionary <string, TValue> to find the corresponding value.
Let's talk about the shortcomings of this implementation (it seems that there is no need ...), First, if DataTable is used, the efficiency will be greatly reduced. Second, the maximum length of the array must be notified in advance. If the maximum length affects the performance, the data cannot be added because the number is reduced.
The following describes the correct implementation method.
1. MultiKeyDictionary <TKey, TValue> is a Dictionary <TKey,
A special case of TValue>, which is equivalent,
Replace TKey in TValue> with TKey [], so you should make the MultiKeyDictionary <TKey,
TValue> inherits Dictionary <TKey [], TValue>.
Second, the remaining question is how to modify the TKey [] Judgment. If Dictionary <TKey [],
TValue> if this extension is not left behind, the inheritance cannot be directly used. Let's take a look at Dictionary <TKey,
TValue> constructor, it is not difficult to find a public Dictionary (IEqualityComparer <TKey>
Comparer). What is the IEqualityComparer <TKey> interface? It contains bool Equals (T x,
T y); int GetHashCode (T obj); two methods, that is, through which you can modify the object judgment (including GetHashCode ).
Third, I believe it is clear that writing a class to implement the IEqualityComparer <TKey []> interface is
When MultiKeyDictionary <TKey, TValue> is called, <TKey [],
TValue> is a parameter-based structure that passes in an object that complies with the IEqualityComparer <TKey []> interface.
MultiKeyDictionary, and owns all Dictionary <TKey [],
TValue> function. If necessary, you can also add your own members.
Finally, note the relationship between GetHashCode and Equals:
1. The GetHashCode is equal, and the object may not be Equals.
2. The object Equals and GetHashCode must be equal.
3. The GetHashCode is not equal, and the object must not be Equals.
For more details, refer to MSDN.