创建自定义通用集合
Create custom generic collection
我想创建一个自定义通用集合,如果元素少于 10 个,它将存储在 List<>
中,如果元素更多,则存储在 SortedList<>
中。
我为 SortedList<>
实现了 ICollection(KeyValuePair)
,为 List<>
实现了 ICollection<>
,但是我不明白我接下来应该做什么。有人可以给我一个提示,应该如何实现 'store elements in List<>
if there are less then 10 of them or in SortedList<>
if there are more' 部分?
class CustomCollection<T, V> : ICollection<KeyValuePair<T, V>>, ICollection<T>
{
private readonly ICollection<T> _list = new List<T>();
private readonly ICollection<KeyValuePair<T, V>> _sortlist = new SortedList<T, V>();
public void Add(KeyValuePair<T, V> item)
{
_sortlist.Add(item);
}
public void Add(T item)
{
_list.Add(item);
}
}
这里有完整的实现。它很长,完全未经测试 :-) 你可以愉快地调试它。
有一些有趣的地方:两个比较器的使用(不是一个好主意),null
的处理是如何完成的(它抛出 NullReferenceException
,就像SortedList) 以及各种 Add
、Remove
、Clear
中集合之间的切换是如何完成的。请注意,通常 SortedList
"hides" 所有直接处理 KeyValuePair<,>
的方法。我选择做同样的事情。其他注意事项:"search" 在 List<>
我做线性搜索。更聪明(更快)的做法是 List.BinarySearch
.
public class CustomCollection<TKey, TValue> : IDictionary<TKey, TValue>
{
protected List<KeyValuePair<TKey, TValue>> List { get; set; }
protected SortedList<TKey, TValue> SortedList { get; set; }
// Two comparers needed: an EqualityComparer and a Comparer to sort
// We could simply use the Comparer and compare the result to 0
// instead of using an EqualityComparer and a Comparer
protected readonly EqualityComparer<TKey> EqualityComparer = EqualityComparer<TKey>.Default;
protected readonly Comparer<TKey> Comparer = Comparer<TKey>.Default;
public int MaxCapacityList { get; protected set; }
public CustomCollection(int maxCapacityList = 10)
{
MaxCapacityList = maxCapacityList;
if (maxCapacityList > 0)
{
List = new List<KeyValuePair<TKey, TValue>>();
}
else
{
SortedList = new SortedList<TKey, TValue>();
}
}
public bool IsUsingList
{
get
{
return List != null;
}
}
public void Add(TKey key, TValue value)
{
if (IsUsingList)
{
if (key == null)
{
throw new ArgumentNullException();
}
if (List.Any(x => EqualityComparer.Equals(x.Key, key)))
{
throw new ArgumentException();
}
}
if (IsUsingList && List.Count < MaxCapacityList)
{
List.Add(new KeyValuePair<TKey, TValue>(key, value));
// Only place we need to sort. Only "real" Add method
List.Sort((x, y) => Comparer.Compare(x.Key, y.Key));
}
else
{
if (IsUsingList && List.Count == MaxCapacityList)
{
SortedList = new SortedList<TKey, TValue>();
foreach (var kv in List)
{
SortedList.Add(kv.Key, kv.Value);
}
List = null;
}
SortedList.Add(key, value);
}
}
public bool ContainsKey(TKey key)
{
if (IsUsingList)
{
if (key == null)
{
throw new ArgumentNullException();
}
if (List.Any(x => EqualityComparer.Equals(x.Key, key)))
{
return true;
}
return false;
}
return SortedList.ContainsKey(key);
}
public ICollection<TKey> Keys
{
get
{
if (IsUsingList)
{
return List.ConvertAll(x => x.Key);
}
return SortedList.Keys;
}
}
public bool Remove(TKey key)
{
if (IsUsingList)
{
if (key == null)
{
throw new ArgumentNullException();
}
for (int ix = 0; ix < List.Count; ix++)
{
if (EqualityComparer.Equals(List[ix].Key, key))
{
List.RemoveAt(ix);
return true;
}
}
return false;
}
bool result = SortedList.Remove(key);
if (result && SortedList.Count == MaxCapacityList && MaxCapacityList > 0)
{
List = new List<KeyValuePair<TKey, TValue>>();
foreach (var kv in SortedList)
{
List.Add(new KeyValuePair<TKey, TValue>(kv.Key, kv.Value));
}
SortedList = null;
}
return result;
}
public bool TryGetValue(TKey key, out TValue value)
{
if (IsUsingList)
{
if (key == null)
{
throw new ArgumentNullException();
}
for (int i = 0; i < List.Count; i++)
{
if (EqualityComparer.Equals(List[i].Key, key))
{
value = List[i].Value;
return true;
}
}
value = default(TValue);
return false;
}
return SortedList.TryGetValue(key, out value);
}
public ICollection<TValue> Values
{
get
{
if (IsUsingList)
{
return List.ConvertAll(x => x.Value);
}
return SortedList.Values;
}
}
public TValue this[TKey key]
{
get
{
if (IsUsingList)
{
if (key == null)
{
throw new ArgumentNullException();
}
for (int ix = 0; ix < List.Count; ix++)
{
if (EqualityComparer.Equals(List[ix].Key, key))
{
return List[ix].Value;
}
}
throw new KeyNotFoundException();
}
return SortedList[key];
}
set
{
if (IsUsingList)
{
if (key == null)
{
throw new ArgumentNullException();
}
for (int ix = 0; ix < List.Count; ix++)
{
if (EqualityComparer.Equals(List[ix].Key, key))
{
List[ix] = new KeyValuePair<TKey, TValue>(key, value);
return;
}
}
Add(key, value);
return;
}
SortedList[key] = value;
}
}
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
Add(item.Key, item.Value);
}
public void Clear()
{
if (IsUsingList)
{
List.Clear();
}
else
{
if (MaxCapacityList > 0)
{
List = new List<KeyValuePair<TKey, TValue>>();
SortedList = null;
}
else
{
SortedList.Clear();
}
}
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
if (IsUsingList)
{
if (item.Key == null)
{
throw new ArgumentNullException();
}
return List.Any(x => EqualityComparer.Equals(x.Key, item.Key));
}
return ((ICollection<KeyValuePair<TKey, TValue>>)SortedList).Contains(item);
}
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
if (IsUsingList)
{
List.CopyTo(array, arrayIndex);
return;
}
((ICollection<KeyValuePair<TKey, TValue>>)SortedList).CopyTo(array, arrayIndex);
}
public int Count
{
get { return IsUsingList ? List.Count : SortedList.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
if (IsUsingList)
{
if (item.Key == null)
{
throw new ArgumentNullException();
}
for (int ix = 0; ix < List.Count; ix++)
{
if (EqualityComparer.Equals(List[ix].Key, item.Key))
{
var comparer2 = EqualityComparer<TValue>.Default;
if (comparer2.Equals(List[ix].Value, item.Value))
{
List.RemoveAt(ix);
return true;
}
return false;
}
}
return false;
}
bool result = ((ICollection<KeyValuePair<TKey, TValue>>)SortedList).Remove(item);
if (result && SortedList.Count == MaxCapacityList && MaxCapacityList > 0)
{
List = new List<KeyValuePair<TKey, TValue>>();
foreach (var kv in SortedList)
{
List.Add(new KeyValuePair<TKey, TValue>(kv.Key, kv.Value));
}
SortedList = null;
}
return result;
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return IsUsingList ? List.GetEnumerator() : SortedList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
// Chained to the other GetEnumerator()
return GetEnumerator();
}
}
我想创建一个自定义通用集合,如果元素少于 10 个,它将存储在 List<>
中,如果元素更多,则存储在 SortedList<>
中。
我为 SortedList<>
实现了 ICollection(KeyValuePair)
,为 List<>
实现了 ICollection<>
,但是我不明白我接下来应该做什么。有人可以给我一个提示,应该如何实现 'store elements in List<>
if there are less then 10 of them or in SortedList<>
if there are more' 部分?
class CustomCollection<T, V> : ICollection<KeyValuePair<T, V>>, ICollection<T>
{
private readonly ICollection<T> _list = new List<T>();
private readonly ICollection<KeyValuePair<T, V>> _sortlist = new SortedList<T, V>();
public void Add(KeyValuePair<T, V> item)
{
_sortlist.Add(item);
}
public void Add(T item)
{
_list.Add(item);
}
}
这里有完整的实现。它很长,完全未经测试 :-) 你可以愉快地调试它。
有一些有趣的地方:两个比较器的使用(不是一个好主意),null
的处理是如何完成的(它抛出 NullReferenceException
,就像SortedList) 以及各种 Add
、Remove
、Clear
中集合之间的切换是如何完成的。请注意,通常 SortedList
"hides" 所有直接处理 KeyValuePair<,>
的方法。我选择做同样的事情。其他注意事项:"search" 在 List<>
我做线性搜索。更聪明(更快)的做法是 List.BinarySearch
.
public class CustomCollection<TKey, TValue> : IDictionary<TKey, TValue>
{
protected List<KeyValuePair<TKey, TValue>> List { get; set; }
protected SortedList<TKey, TValue> SortedList { get; set; }
// Two comparers needed: an EqualityComparer and a Comparer to sort
// We could simply use the Comparer and compare the result to 0
// instead of using an EqualityComparer and a Comparer
protected readonly EqualityComparer<TKey> EqualityComparer = EqualityComparer<TKey>.Default;
protected readonly Comparer<TKey> Comparer = Comparer<TKey>.Default;
public int MaxCapacityList { get; protected set; }
public CustomCollection(int maxCapacityList = 10)
{
MaxCapacityList = maxCapacityList;
if (maxCapacityList > 0)
{
List = new List<KeyValuePair<TKey, TValue>>();
}
else
{
SortedList = new SortedList<TKey, TValue>();
}
}
public bool IsUsingList
{
get
{
return List != null;
}
}
public void Add(TKey key, TValue value)
{
if (IsUsingList)
{
if (key == null)
{
throw new ArgumentNullException();
}
if (List.Any(x => EqualityComparer.Equals(x.Key, key)))
{
throw new ArgumentException();
}
}
if (IsUsingList && List.Count < MaxCapacityList)
{
List.Add(new KeyValuePair<TKey, TValue>(key, value));
// Only place we need to sort. Only "real" Add method
List.Sort((x, y) => Comparer.Compare(x.Key, y.Key));
}
else
{
if (IsUsingList && List.Count == MaxCapacityList)
{
SortedList = new SortedList<TKey, TValue>();
foreach (var kv in List)
{
SortedList.Add(kv.Key, kv.Value);
}
List = null;
}
SortedList.Add(key, value);
}
}
public bool ContainsKey(TKey key)
{
if (IsUsingList)
{
if (key == null)
{
throw new ArgumentNullException();
}
if (List.Any(x => EqualityComparer.Equals(x.Key, key)))
{
return true;
}
return false;
}
return SortedList.ContainsKey(key);
}
public ICollection<TKey> Keys
{
get
{
if (IsUsingList)
{
return List.ConvertAll(x => x.Key);
}
return SortedList.Keys;
}
}
public bool Remove(TKey key)
{
if (IsUsingList)
{
if (key == null)
{
throw new ArgumentNullException();
}
for (int ix = 0; ix < List.Count; ix++)
{
if (EqualityComparer.Equals(List[ix].Key, key))
{
List.RemoveAt(ix);
return true;
}
}
return false;
}
bool result = SortedList.Remove(key);
if (result && SortedList.Count == MaxCapacityList && MaxCapacityList > 0)
{
List = new List<KeyValuePair<TKey, TValue>>();
foreach (var kv in SortedList)
{
List.Add(new KeyValuePair<TKey, TValue>(kv.Key, kv.Value));
}
SortedList = null;
}
return result;
}
public bool TryGetValue(TKey key, out TValue value)
{
if (IsUsingList)
{
if (key == null)
{
throw new ArgumentNullException();
}
for (int i = 0; i < List.Count; i++)
{
if (EqualityComparer.Equals(List[i].Key, key))
{
value = List[i].Value;
return true;
}
}
value = default(TValue);
return false;
}
return SortedList.TryGetValue(key, out value);
}
public ICollection<TValue> Values
{
get
{
if (IsUsingList)
{
return List.ConvertAll(x => x.Value);
}
return SortedList.Values;
}
}
public TValue this[TKey key]
{
get
{
if (IsUsingList)
{
if (key == null)
{
throw new ArgumentNullException();
}
for (int ix = 0; ix < List.Count; ix++)
{
if (EqualityComparer.Equals(List[ix].Key, key))
{
return List[ix].Value;
}
}
throw new KeyNotFoundException();
}
return SortedList[key];
}
set
{
if (IsUsingList)
{
if (key == null)
{
throw new ArgumentNullException();
}
for (int ix = 0; ix < List.Count; ix++)
{
if (EqualityComparer.Equals(List[ix].Key, key))
{
List[ix] = new KeyValuePair<TKey, TValue>(key, value);
return;
}
}
Add(key, value);
return;
}
SortedList[key] = value;
}
}
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
Add(item.Key, item.Value);
}
public void Clear()
{
if (IsUsingList)
{
List.Clear();
}
else
{
if (MaxCapacityList > 0)
{
List = new List<KeyValuePair<TKey, TValue>>();
SortedList = null;
}
else
{
SortedList.Clear();
}
}
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
if (IsUsingList)
{
if (item.Key == null)
{
throw new ArgumentNullException();
}
return List.Any(x => EqualityComparer.Equals(x.Key, item.Key));
}
return ((ICollection<KeyValuePair<TKey, TValue>>)SortedList).Contains(item);
}
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
if (IsUsingList)
{
List.CopyTo(array, arrayIndex);
return;
}
((ICollection<KeyValuePair<TKey, TValue>>)SortedList).CopyTo(array, arrayIndex);
}
public int Count
{
get { return IsUsingList ? List.Count : SortedList.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
if (IsUsingList)
{
if (item.Key == null)
{
throw new ArgumentNullException();
}
for (int ix = 0; ix < List.Count; ix++)
{
if (EqualityComparer.Equals(List[ix].Key, item.Key))
{
var comparer2 = EqualityComparer<TValue>.Default;
if (comparer2.Equals(List[ix].Value, item.Value))
{
List.RemoveAt(ix);
return true;
}
return false;
}
}
return false;
}
bool result = ((ICollection<KeyValuePair<TKey, TValue>>)SortedList).Remove(item);
if (result && SortedList.Count == MaxCapacityList && MaxCapacityList > 0)
{
List = new List<KeyValuePair<TKey, TValue>>();
foreach (var kv in SortedList)
{
List.Add(new KeyValuePair<TKey, TValue>(kv.Key, kv.Value));
}
SortedList = null;
}
return result;
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return IsUsingList ? List.GetEnumerator() : SortedList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
// Chained to the other GetEnumerator()
return GetEnumerator();
}
}