forked from sin365/AxibugEmuOnline
133 lines
4.8 KiB
C#
133 lines
4.8 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
namespace AxibugEmuOnline.Client.InputDevices
|
|
{
|
|
/// <summary>
|
|
/// 双向字典
|
|
/// </summary>
|
|
/// <typeparam name="TKey"></typeparam>
|
|
/// <typeparam name="TValue"></typeparam>
|
|
public class DualWayDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary
|
|
where TKey : notnull
|
|
where TValue : notnull
|
|
{
|
|
private readonly Dictionary<TKey, TValue> _forward = new();
|
|
private readonly Dictionary<TValue, TKey> _reverse = new();
|
|
|
|
// 显式实现非泛型接口
|
|
bool IDictionary.IsFixedSize => false;
|
|
bool IDictionary.IsReadOnly => false;
|
|
bool ICollection.IsSynchronized => false;
|
|
object ICollection.SyncRoot => ((ICollection)_forward).SyncRoot;
|
|
|
|
// 泛型接口实现
|
|
public TValue this[TKey key]
|
|
{
|
|
get => _forward[key];
|
|
set
|
|
{
|
|
if (_forward.TryGetValue(key, out var oldValue))
|
|
_reverse.Remove(oldValue);
|
|
_forward[key] = value;
|
|
_reverse[value] = key;
|
|
}
|
|
}
|
|
|
|
object? IDictionary.this[object key]
|
|
{
|
|
get => key is TKey k ? _forward[k] : null;
|
|
set
|
|
{
|
|
if (key is TKey tk && value is TValue tv)
|
|
this[tk] = tv;
|
|
}
|
|
}
|
|
|
|
public ICollection<TKey> Keys => _forward.Keys;
|
|
public ICollection<TValue> Values => _forward.Values;
|
|
|
|
ICollection IDictionary.Keys => _forward.Keys;
|
|
ICollection IDictionary.Values => _forward.Values;
|
|
|
|
public int Count => _forward.Count;
|
|
public bool IsReadOnly => false;
|
|
|
|
// 双向查询扩展
|
|
public bool TryGetKey(TValue value, out TKey key) => _reverse.TryGetValue(value, out key);
|
|
public bool TryGetValue(TKey key, out TValue value) => _forward.TryGetValue(key, out value);
|
|
|
|
// 接口方法实现
|
|
public void Add(TKey key, TValue value)
|
|
{
|
|
if (_forward.ContainsKey(key) || _reverse.ContainsKey(value))
|
|
throw new ArgumentException("键或值已存在");
|
|
_forward.Add(key, value);
|
|
_reverse.Add(value, key);
|
|
}
|
|
|
|
public void Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value);
|
|
|
|
void IDictionary.Add(object key, object value)
|
|
{
|
|
if (key is TKey k && value is TValue v)
|
|
Add(k, v);
|
|
else
|
|
throw new ArgumentException("类型不匹配");
|
|
}
|
|
|
|
public bool Contains(object key) => key is TKey k && _forward.ContainsKey(k);
|
|
public bool Contains(KeyValuePair<TKey, TValue> item) => _forward.TryGetValue(item.Key, out var v) && v.Equals(item.Value);
|
|
public bool ContainsKey(TKey key) => _forward.ContainsKey(key);
|
|
|
|
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
|
{
|
|
((ICollection<KeyValuePair<TKey, TValue>>)_forward).CopyTo(array, arrayIndex);
|
|
}
|
|
|
|
public void CopyTo(Array array, int index)
|
|
{
|
|
((ICollection)_forward).CopyTo(array, index);
|
|
}
|
|
|
|
public bool Remove(TKey key)
|
|
{
|
|
if (!_forward.Remove(key, out var value)) return false;
|
|
_reverse.Remove(value);
|
|
return true;
|
|
}
|
|
|
|
public bool Remove(KeyValuePair<TKey, TValue> item) => Remove(item.Key);
|
|
|
|
void IDictionary.Remove(object key)
|
|
{
|
|
if (key is TKey k) Remove(k);
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
_forward.Clear();
|
|
_reverse.Clear();
|
|
}
|
|
|
|
// 枚举器实现
|
|
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => _forward.GetEnumerator();
|
|
IDictionaryEnumerator IDictionary.GetEnumerator() => new DictionaryEnumerator(_forward.GetEnumerator());
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
|
|
// 非泛型枚举器适配器
|
|
private class DictionaryEnumerator : IDictionaryEnumerator
|
|
{
|
|
private readonly IEnumerator<KeyValuePair<TKey, TValue>> _enumerator;
|
|
public DictionaryEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> enumerator) => _enumerator = enumerator;
|
|
|
|
public DictionaryEntry Entry => new(_enumerator.Current.Key, _enumerator.Current.Value);
|
|
public object Key => _enumerator.Current.Key;
|
|
public object? Value => _enumerator.Current.Value;
|
|
public object Current => Entry;
|
|
public bool MoveNext() => _enumerator.MoveNext();
|
|
public void Reset() => _enumerator.Reset();
|
|
}
|
|
}
|
|
} |