我正在寻找一个 C# 通用容器,它是一个List<T>
,但不允许重复元素。
换句话说,它是一个Set<T>
, 但也可以通过[index]
运算符访问。
谢谢。
我正在寻找一个 C# 通用容器,它是一个List<T>
,但不允许重复元素。
换句话说,它是一个Set<T>
, 但也可以通过[index]
运算符访问。
谢谢。
正如评论中所建议的那样,您可以IList<T>
将该委托实现给内部List<T>
实例,并使用 a 来保护添加和删除调用HashSet<T>
:
public class UniqueList<T> : IList<T>
{
private readonly List<T> list=new List<T>();
private readonly HashSet<T> set=new HashSet<T>();
public IEnumerator<T> GetEnumerator()
{
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
if(set.Add(item))
{
list.Add(item);
}
}
public void Clear()
{
set.Clear();
list.Clear();
}
public bool Contains(T item)
{
return set.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
list.CopyTo(array,arrayIndex);
}
public bool Remove(T item)
{
if(set.Remove(item))
{
list.Remove(item);
return true;
}
return false;
}
public int Count { get { return list.Count; } }
public bool IsReadOnly { get { return false; } }
public int IndexOf(T item)
{
return list.IndexOf(item);
}
public void Insert(int index, T item)
{
if(set.Add(item))
{
list.Insert(index, item);
}
}
public void RemoveAt(int index)
{
T item = list[index];
set.Remove(item);
list.RemoveAt(index);
}
public T this[int index]
{
get { return list[index]; }
set {
T item = list[index];
set.Remove(item);
if(set.Add(value))
{
list[index] = value;
}
else
{
set.Add(item);
throw new Exception();
}
}
}
}
我没有编译这段代码,但你明白了......
框架中没有提供这样的东西(并且HashSet<T>
不保证任何特定的顺序,所以你不能作弊ElementAt
)。您可以使用的最接近的内置SortedList<T,anything>
内容类似于(“任何东西”都无关紧要,可以是T
, int
, 等等),例如:
var data = new SortedList<string, int>();
data["abc"] = 1;
data["def"] = 1;
data["abc"] = 1;
var thisIsTrue = data.ContainsKey("def");
var thisIsFalse = data.ContainsKey("ghi");
for (int i = 0; i < data.Count; i++) // 2 iterations
Console.WriteLine(data.Keys[i]); // abc, def
然而; 重要的是要注意这里保证的顺序是key order,而不是插入顺序。键的索引可通过data.IndexOfKey
.
您可以使用OrderedDictionary。如果您将您的类型用于键和值类型,并使用相同的对象作为键和值,您将获得所需的行为(您也可以使用键集合进行基于索引的检索;并将虚拟数据粘贴到值中,但我不确定你会得到什么)。