问题遇到的现象
我想以多线程的办法去处理表格里的数据,并在其方法内部进行业务操作,于是我自定义了一个字典类MyDictionary。
但我想要给进行排序操作的时候,程序报错"未将对象引用到实例",总数量Count没有变化,但item都是对象的默认值。
我是漏掉了什么步骤了吗?
运行结果及报错内容
问题相关代码
public class MyDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
{
/// <summary>
/// 数据源
/// </summary>
private ConcurrentDictionary<TKey, TValue> _items;
public MyDictionary()
{
_items = new ConcurrentDictionary<TKey, TValue>();
}
/// <summary>
/// 获取或设置具有指定键的元素
/// </summary>
/// <param name="key">要获取或设置的元素的键</param>
/// <returns></returns>
public TValue this[TKey key]
{
get
{
return _items[key];
}
set
{
if (_items.ContainsKey(key))
_items[key] = value;
else
Add(key, value);
}
}
/// <summary>
/// 获取或设置具有指定键的元素
/// </summary>
/// <param name="key">要获取或设置的元素的键</param>
/// <returns></returns>
public object this[object key] { get { return ((IDictionary)_items)[key]; } set { ((IDictionary)_items)[key] = value; } }
/// <summary>
/// 获得一个包含字典中的键的集合
/// </summary>
public ICollection<TKey> Keys { get { return _items.Keys; } }
/// <summary>
/// 获得一个包含字典中的键的集合
/// </summary>
ICollection IDictionary.Keys { get { return ((IDictionary)_items).Keys; } }
/// <summary>
/// 获得一个包含字典中的值的集合
/// </summary>
public ICollection<TValue> Values { get { return _items.Values; } }
/// <summary>
/// 获得一个包含字典中的值的集合
/// </summary>
ICollection IDictionary.Values { get { return ((IDictionary)_items).Values; } }
/// <summary>
/// 获取包含在字典中的键/值对的数目
/// </summary>
public int Count { get { return _items.Count(); } }
/// <summary>
/// 获取一个值,该值指示<see cref="ICollection"/>是否为只读
/// </summary>
public bool IsReadOnly { get { return false; } }
private object _syncRoot;
/// <summary>
/// 获取可用于同步对<see cref="ArrayList"/>的访问的对象
/// </summary>
public object SyncRoot
{
get
{
if (_syncRoot == null)
Interlocked.CompareExchange(ref this._syncRoot, new object(), null);
return _syncRoot;
}
}
/// <summary>
/// 获取一个值,该值指示是否同步对<see cref="ArrayList"/>的访问(线程安全)
/// </summary>
public bool IsSynchronized { get { return true; } }
/// <summary>
/// 获取一个值,该值指示是否<see cref="ICollection"/>对象具有固定的大小
/// </summary>
public bool IsFixedSize { get { return false; } }
/// <summary>
/// 将指定的键和值添加到字典中
/// </summary>
/// <param name="key">要添加的元素的键</param>
/// <param name="value">要添加的元素的值。对于引用类型,该值可以为 null</param>
public void Add(TKey key, TValue value)
{
if (!_items.TryAdd(key, value))
throw new ArgumentException("字典中已存在具有相同键的元素");
}
/// <summary>
/// 将指定的键和值添加到字典中
/// </summary>
/// <param name="item">要添加键/值对</param>
public void Add(KeyValuePair<TKey, TValue> item)
{
Add(item.Key, item.Value);
}
/// <summary>
/// 将指定的键和值添加到字典中
/// </summary>
/// <param name="key">要添加的元素的键</param>
/// <param name="value">要添加的元素的值。对于引用类型,该值可以为 null</param>
void IDictionary.Add(object key, object value)
{
TKey _key = ConvertKey(key);
((IDictionary)_items).Add(_key, (int)value);
}
/// <summary>
/// 将所有元素从字典中移除
/// </summary>
public void Clear()
{
_items.Clear();
}
/// <summary>
/// 确定是否字典中包含指定键
/// </summary>
/// <param name="key">定位的键</param>
/// <returns></returns>
public bool ContainsKey(TKey key)
{
return _items.ContainsKey(key);
}
/// <summary>
/// 确定是否字典中包含指定键
/// </summary>
/// <param name="item">定位的键/值对</param>
/// <returns></returns>
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return _items.Contains<KeyValuePair<TKey, TValue>>(item);
}
/// <summary>
/// 确定是否字典中包含指定键
/// </summary>
/// <param name="key">定位的键</param>
/// <returns></returns>
public bool Contains(object key)
{
TKey _key = ConvertKey(key);
return _items.ContainsKey(_key);
}
/// <summary>
/// 从第一个元素开始复制<see cref="Array"/>中的一系列元素,将它们粘贴到另一<see cref="Array"/>中(从第一个元素开始)
/// </summary>
/// <param name="array">接收数据的<see cref="Array"/></param>
/// <param name="index">一个 32 位整数,它表示要复制的元素数目</param>
public void CopyTo(Array array, int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException("index小于零");
if (index > array.Length)
throw new ArgumentException("index大于字典中的元素数");
if (index > array.Length || array == null)
throw new ArgumentNullException("未将对象引用到实例");
Array.Copy(_items.ToArray(), array, index);
}
/// <summary>
/// 从第一个元素开始复制<see cref="Array"/>中的一系列元素,将它们粘贴到另一<see cref="Array"/>中(从第一个元素开始)
/// </summary>
/// <param name="array">接收数据的<see cref="Array"/></param>
/// <param name="arrayIndex">一个 32 位整数,它表示要复制的元素数目</param>
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
Array.Copy(_items.ToArray(), array, arrayIndex);
}
/// <summary>
/// 将带有指定键的值从字典中移除
/// </summary>
/// <param name="key">要移除的元素的键</param>
/// <returns></returns>
public bool Remove(TKey key)
{
TValue outValue = default(TValue);
return _items.TryRemove(key, out outValue);
}
/// <summary>
/// 将带有指定键/值对从字典中移除
/// </summary>
/// <param name="key">要移除的键/值对</param>
/// <returns></returns>
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return Remove(item.Key);
}
/// <summary>
/// 将带有指定键的值从字典中移除
/// </summary>
/// <param name="key">要移除的元素的键</param>
/// <returns></returns>
void IDictionary.Remove(object key)
{
TKey _key = ConvertKey(key);
((IDictionary)_items).Remove(_key);
}
/// <summary>
/// 尝试从字典中获取与指定的键关联的值
/// </summary>
/// <param name="key">要获取的值的键</param>
/// <param name="value">当此方法返回时,将包含字典中具有指定键的对象;如果操作失败,则包含类型的默认值</param>
/// <returns></returns>
public bool TryGetValue(TKey key, out TValue value)
{
return _items.TryGetValue(key, out value);
}
/// <summary>
/// 返回一个循环访问集合的枚举器
/// </summary>
/// <returns></returns>
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(this, Enumerator.KeyValuePair);
}
/// <summary>
/// 返回一个循环访问集合的枚举器
/// </summary>
/// <returns></returns>
IDictionaryEnumerator IDictionary.GetEnumerator()
{
return new Enumerator(this, Enumerator.DictEntry);
}
/// <summary>
/// 将<see cref="object"/>转换为<see cref="TKey"/>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
private TKey ConvertKey(object key)
{
TKey _key = key as TKey;
if (key == null)
throw new InvalidCastException("key不是有效类型");
return _key;
}
Enumerator GetEnumerator()
{
return new Enumerator(this, Enumerator.KeyValuePair);
}
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
return new Enumerator(this, Enumerator.KeyValuePair);
}
private struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>, IDictionaryEnumerator
{
private Dictionary<TKey, TValue> dictionary;
private KeyValuePair<TKey, TValue> current;
private int index;
private int getEnumeratorRetType; // What should Enumerator.Current return?
internal const int DictEntry = 1;
internal const int KeyValuePair = 2;
public Enumerator(MyDictionary<TKey, TValue> source, int _getEnumeratorRetType)
{
dictionary = new Dictionary<TKey, TValue>((IDictionary<TKey, TValue>)source._items);
index = 0;
getEnumeratorRetType = _getEnumeratorRetType;
current = new KeyValuePair<TKey, TValue>();
}
public KeyValuePair<TKey, TValue> Current { get { return current; } }
object IEnumerator.Current
{
get
{
if (getEnumeratorRetType == DictEntry)
return new DictionaryEntry(current.Key, current.Value);
else
return new KeyValuePair<TKey, TValue>(current.Key, current.Value);
}
}
object IDictionaryEnumerator.Key { get { return current.Key; } }
object IDictionaryEnumerator.Value { get { return current.Value; } }
DictionaryEntry IDictionaryEnumerator.Entry
{
get
{
return new DictionaryEntry(current.Key, current.Value);
}
}
public void Dispose()
{
}
public bool MoveNext()
{
while (index < dictionary.Count)
{
current = new KeyValuePair<TKey, TValue>(dictionary.ElementAt(index).Key, dictionary.ElementAt(index).Value);
index++;
return true;
}
index = dictionary.Count + 1;
current = new KeyValuePair<TKey, TValue>();
return false;
}
void IEnumerator.Reset()
{
index = 0;
current = new KeyValuePair<TKey, TValue>();
}
}
}