C#创建安全的字典(Dictionary)存储结构
程序员文章站
2022-06-15 18:29:21
在上面介绍过栈(stack)的存储结构,接下来介绍另一种存储结构字典(dictionary)。 字典(dictionary)里面的每一个元素都是一个键值对(由二个元素组成:...
在上面介绍过栈(stack)的存储结构,接下来介绍另一种存储结构字典(dictionary)。 字典(dictionary)里面的每一个元素都是一个键值对(由二个元素组成:键和值) 键必须是唯一的,而值不需要唯一的,键和值都可以是任何类型。字典(dictionary)是常用于查找和排序的列表。
接下来看一下dictionary的部分方法和类的底层实现代码:
1.add:将指定的键和值添加到字典中。
public void add(tkey key, tvalue value) { insert(key, value, true); } private void insert(tkey key, tvalue value, bool add) { if( key == null ) { throwhelper.throwargumentnullexception(exceptionargument.key); } if (buckets == null) initialize(0); int hashcode = comparer.gethashcode(key) & 0x7fffffff; int targetbucket = hashcode % buckets.length; #if feature_randomized_string_hashing int collisioncount = 0; #endif for (int i = buckets[targetbucket]; i >= 0; i = entries[i].next) { if (entries[i].hashcode == hashcode && comparer.equals(entries[i].key, key)) { if (add) { throwhelper.throwargumentexception(exceptionresource.argument_addingduplicate); } entries[i].value = value; version++; return; } #if feature_randomized_string_hashing collisioncount++; #endif } int index; if (freecount > 0) { index = freelist; freelist = entries[index].next; freecount--; } else { if (count == entries.length) { resize(); targetbucket = hashcode % buckets.length; } index = count; count++; } entries[index].hashcode = hashcode; entries[index].next = buckets[targetbucket]; entries[index].key = key; entries[index].value = value; buckets[targetbucket] = index; version++; #if feature_randomized_string_hashing if(collisioncount > hashhelpers.hashcollisionthreshold && hashhelpers.iswellknownequalitycomparer(comparer)) { comparer = (iequalitycomparer<tkey>) hashhelpers.getrandomizedequalitycomparer(comparer); resize(entries.length, true); } #endif }
2.clear():从 dictionary<tkey, tvalue> 中移除所有的键和值。
public void clear() { if (count > 0) { for (int i = 0; i < buckets.length; i++) buckets[i] = -1; array.clear(entries, 0, count); freelist = -1; count = 0; freecount = 0; version++; } }
3.remove():从 dictionary<tkey, tvalue> 中移除所指定的键的值。
public bool remove(tkey key) { if(key == null) { throwhelper.throwargumentnullexception(exceptionargument.key); } if (buckets != null) { int hashcode = comparer.gethashcode(key) & 0x7fffffff; int bucket = hashcode % buckets.length; int last = -1; for (int i = buckets[bucket]; i >= 0; last = i, i = entries[i].next) { if (entries[i].hashcode == hashcode && comparer.equals(entries[i].key, key)) { if (last < 0) { buckets[bucket] = entries[i].next; } else { entries[last].next = entries[i].next; } entries[i].hashcode = -1; entries[i].next = freelist; entries[i].key = default(tkey); entries[i].value = default(tvalue); freelist = i; freecount++; version++; return true; } } } return false; }
4.getenumerator():返回循环访问 dictionary<tkey, tvalue> 的枚举器。
public enumerator getenumerator() { return new enumerator(this, enumerator.keyvaluepair); } [serializable] public struct enumerator: ienumerator<keyvaluepair<tkey,tvalue>>, idictionaryenumerator { private dictionary<tkey,tvalue> dictionary; private int version; private int index; private keyvaluepair<tkey,tvalue> current; private int getenumeratorrettype; // what should enumerator.current return? internal const int dictentry = 1; internal const int keyvaluepair = 2; internal enumerator(dictionary<tkey,tvalue> dictionary, int getenumeratorrettype) { this.dictionary = dictionary; version = dictionary.version; index = 0; this.getenumeratorrettype = getenumeratorrettype; current = new keyvaluepair<tkey, tvalue>(); } public bool movenext() { if (version != dictionary.version) { throwhelper.throwinvalidoperationexception(exceptionresource.invalidoperation_enumfailedversion); } // use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends. // dictionary.count+1 could be negative if dictionary.count is int32.maxvalue while ((uint)index < (uint)dictionary.count) { if (dictionary.entries[index].hashcode >= 0) { current = new keyvaluepair<tkey, tvalue>(dictionary.entries[index].key, dictionary.entries[index].value); index++; return true; } index++; } index = dictionary.count + 1; current = new keyvaluepair<tkey, tvalue>(); return false; } public keyvaluepair<tkey,tvalue> current { get { return current; } } public void dispose() { } object ienumerator.current { get { if( index == 0 || (index == dictionary.count + 1)) { throwhelper.throwinvalidoperationexception(exceptionresource.invalidoperation_enumopcanthappen); } if (getenumeratorrettype == dictentry) { return new system.collections.dictionaryentry(current.key, current.value); } else { return new keyvaluepair<tkey, tvalue>(current.key, current.value); } } } void ienumerator.reset() { if (version != dictionary.version) { throwhelper.throwinvalidoperationexception(exceptionresource.invalidoperation_enumfailedversion); } index = 0; current = new keyvaluepair<tkey, tvalue>(); } dictionaryentry idictionaryenumerator.entry { get { if( index == 0 || (index == dictionary.count + 1)) { throwhelper.throwinvalidoperationexception(exceptionresource.invalidoperation_enumopcanthappen); } return new dictionaryentry(current.key, current.value); } } object idictionaryenumerator.key { get { if( index == 0 || (index == dictionary.count + 1)) { throwhelper.throwinvalidoperationexception(exceptionresource.invalidoperation_enumopcanthappen); } return current.key; } } object idictionaryenumerator.value { get { if( index == 0 || (index == dictionary.count + 1)) { throwhelper.throwinvalidoperationexception(exceptionresource.invalidoperation_enumopcanthappen); } return current.value; } } }
上面主要是对字典(dictionary)的一些常用方法进行一个简单的说明。接下来主要阐述如何创建安全的字典(dictionary)存储结构。有关线程安全的部分,在这里就不再赘述了。
/// <summary> /// 线程安全通用字典 /// </summary> /// <typeparam name="tkey"></typeparam> /// <typeparam name="tvalue"></typeparam> public class tdictionary<tkey, tvalue> : idictionary<tkey, tvalue> { /// <summary> /// 锁定字典 /// </summary> private readonly readerwriterlockslim _lockdictionary = new readerwriterlockslim(); /// <summary> ///基本字典 /// </summary> private readonly dictionary<tkey, tvalue> _mdictionary; // variables /// <summary> /// 初始化字典对象 /// </summary> public tdictionary() { _mdictionary = new dictionary<tkey, tvalue>(); } /// <summary> /// 初始化字典对象 /// </summary> /// <param name="capacity">字典的初始容量</param> public tdictionary(int capacity) { _mdictionary = new dictionary<tkey, tvalue>(capacity); } /// <summary> ///初始化字典对象 /// </summary> /// <param name="comparer">比较器在比较键时使用</param> public tdictionary(iequalitycomparer<tkey> comparer) { _mdictionary = new dictionary<tkey, tvalue>(comparer); } /// <summary> /// 初始化字典对象 /// </summary> /// <param name="dictionary">其键和值被复制到此对象的字典</param> public tdictionary(idictionary<tkey, tvalue> dictionary) { _mdictionary = new dictionary<tkey, tvalue>(dictionary); } /// <summary> ///初始化字典对象 /// </summary> /// <param name="capacity">字典的初始容量</param> /// <param name="comparer">比较器在比较键时使用</param> public tdictionary(int capacity, iequalitycomparer<tkey> comparer) { _mdictionary = new dictionary<tkey, tvalue>(capacity, comparer); } /// <summary> /// 初始化字典对象 /// </summary> /// <param name="dictionary">其键和值被复制到此对象的字典</param> /// <param name="comparer">比较器在比较键时使用</param> public tdictionary(idictionary<tkey, tvalue> dictionary, iequalitycomparer<tkey> comparer) { _mdictionary = new dictionary<tkey, tvalue>(dictionary, comparer); } public tvalue getvalueaddifnotexist(tkey key, func<tvalue> func) { return _lockdictionary.performusingupgradeablereadlock(() => { tvalue rval; // 如果我们有值,得到它并退出 if (_mdictionary.trygetvalue(key, out rval)) return rval; // 没有找到,所以做函数得到的值 _lockdictionary.performusingwritelock(() => { rval = func.invoke(); // 添加到字典 _mdictionary.add(key, rval); return rval; }); return rval; }); } /// <summary> /// 将项目添加到字典 /// </summary> /// <param name="key">添加的关键</param> /// <param name="value">要添加的值</param> public void add(tkey key, tvalue value) { _lockdictionary.performusingwritelock(() => _mdictionary.add(key, value)); } /// <summary> ///将项目添加到字典 /// </summary> /// <param name="item">要添加的键/值</param> public void add(keyvaluepair<tkey, tvalue> item) { var key = item.key; var value = item.value; _lockdictionary.performusingwritelock(() => _mdictionary.add(key, value)); } /// <summary> /// 如果值不存在,则添加该值。 返回如果值已添加,则为true /// </summary> /// <param name="key">检查的关键,添加</param> /// <param name="value">如果键不存在,则添加的值</param> public bool addifnotexists(tkey key, tvalue value) { bool rval = false; _lockdictionary.performusingwritelock(() => { // 如果不存在,则添加它 if (!_mdictionary.containskey(key)) { // 添加该值并设置标志 _mdictionary.add(key, value); rval = true; } }); return rval; } /// <summary> /// 如果键不存在,则添加值列表。 /// </summary> /// <param name="keys">要检查的键,添加</param> /// <param name="defaultvalue">如果键不存在,则添加的值</param> public void addifnotexists(ienumerable<tkey> keys, tvalue defaultvalue) { _lockdictionary.performusingwritelock(() => { foreach (tkey key in keys) { // 如果不存在,则添加它 if (!_mdictionary.containskey(key)) _mdictionary.add(key, defaultvalue); } }); } public bool addifnotexistselseupdate(tkey key, tvalue value) { var rval = false; _lockdictionary.performusingwritelock(() => { // 如果不存在,则添加它 if (!_mdictionary.containskey(key)) { // 添加该值并设置标志 _mdictionary.add(key, value); rval = true; } else _mdictionary[key] = value; }); return rval; } /// <summary> /// 如果键存在,则更新键的值。 /// </summary> /// <param name="key"></param> /// <param name="newvalue"></param> public bool updatevalueifkeyexists(tkey key, tvalue newvalue) { bool rval = false; _lockdictionary.performusingwritelock(() => { // 如果我们有密钥,然后更新它 if (!_mdictionary.containskey(key)) return; _mdictionary[key] = newvalue; rval = true; }); return rval; } /// <summary> /// 如果键值对存在于字典中,则返回true /// </summary> /// <param name="item">键值对查找</param> public bool contains(keyvaluepair<tkey, tvalue> item) { return _lockdictionary.performusingreadlock(() => ((_mdictionary.containskey(item.key)) && (_mdictionary.containsvalue(item.value)))); } public bool containskey(tkey key) { return _lockdictionary.performusingreadlock(() => _mdictionary.containskey(key)); } /// <summary> /// 如果字典包含此值,则返回true /// </summary> /// <param name="value">找到的值</param> public bool containsvalue(tvalue value) { return _lockdictionary.performusingreadlock(() => _mdictionary.containsvalue(value)); } public icollection<tkey> keys { get { return _lockdictionary.performusingreadlock(() => _mdictionary.keys); } } public bool remove(tkey key) { return _lockdictionary.performusingwritelock(() => (!_mdictionary.containskey(key)) || _mdictionary.remove(key)); } public bool remove(keyvaluepair<tkey, tvalue> item) { return _lockdictionary.performusingwritelock(() => { // 如果键不存在则跳过 tvalue tempval; if (!_mdictionary.trygetvalue(item.key, out tempval)) return false; //如果值不匹配,请跳过 return tempval.equals(item.value) && _mdictionary.remove(item.key); }); } /// <summary> /// 从字典中删除与模式匹配的项 /// </summary> /// <param name="predkey">基于键的可选表达式</param> /// <param name="predvalue">基于值的选项表达式</param> public bool remove(predicate<tkey> predkey, predicate<tvalue> predvalue) { return _lockdictionary.performusingwritelock(() => { // 如果没有键退出 if (_mdictionary.keys.count == 0) return true; //保存要删除的项目列表 var deletelist = new list<tkey>(); // 过程密钥 foreach (var key in _mdictionary.keys) { var ismatch = false; if (predkey != null) ismatch = (predkey(key)); // 如果此项目的值匹配,请添加它 if ((!ismatch) && (predvalue != null) && (predvalue(_mdictionary[key]))) ismatch = true; // 如果我们有匹配,添加到列表 if (ismatch) deletelist.add(key); } // 从列表中删除所有项目 foreach (var item in deletelist) _mdictionary.remove(item); return true; }); } public bool trygetvalue(tkey key, out tvalue value) { _lockdictionary.enterreadlock(); try { return _mdictionary.trygetvalue(key, out value); } finally { _lockdictionary.exitreadlock(); } } public icollection<tvalue> values { get { return _lockdictionary.performusingreadlock(() => _mdictionary.values); } } public tvalue this[tkey key] { get { return _lockdictionary.performusingreadlock(() => _mdictionary[key]); } set { _lockdictionary.performusingwritelock(() => _mdictionary[key] = value); } } /// <summary> /// 清除字典 /// </summary> public void clear() { _lockdictionary.performusingwritelock(() => _mdictionary.clear()); } public void copyto(keyvaluepair<tkey, tvalue>[] array, int arrayindex) { _lockdictionary.performusingreadlock(() => _mdictionary.toarray().copyto(array, arrayindex)); } /// <summary> /// 返回字典中的项目数 /// </summary> public int count { get { return _lockdictionary.performusingreadlock(() => _mdictionary.count); } } public bool isreadonly { get { return false; } } public ienumerator<keyvaluepair<tkey, tvalue>> getenumerator() { dictionary<tkey, tvalue> localdict = null; _lockdictionary.performusingreadlock(() => localdict = new dictionary<tkey, tvalue>(_mdictionary)); return ((ienumerable<keyvaluepair<tkey, tvalue>>)localdict).getenumerator(); } system.collections.ienumerator system.collections.ienumerable.getenumerator() { dictionary<tkey, tvalue> localdict = null; _lockdictionary.performusingreadlock(() => localdict = new dictionary<tkey, tvalue>(_mdictionary)); return localdict.getenumerator(); } }
以上创建安全的字典方法中,主要对字典的一些方法和属性进行重写操作,对某些方法进行锁设置。
以上就是本文的全部内容,希望对大家有所帮助,同时也希望多多支持!
上一篇: C#利用QrCode.Net生成二维码(Qr码)的方法
下一篇: 浅谈C# 中的委托和事件