0

我正在寻找一个 C# 通用容器,它是一个List<T>,但不允许重复元素。

换句话说,它是一个Set<T>, 但也可以通过[index]运算符访问。

谢谢。

4

3 回答 3

1

正如评论中所建议的那样,您可以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();
            }


        }
    }
}

我没有编译这段代码,但你明白了......

于 2012-08-15T05:57:44.173 回答
1

框架中没有提供这样的东西(并且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.

于 2012-08-15T05:58:56.247 回答
0

您可以使用OrderedDictionary。如果您将您的类型用于键和值类型,并使用相同的对象作为键和值,您将获得所需的行为(您也可以使用键集合进行基于索引的检索;并将虚拟数据粘贴到值中,但我不确定你会得到什么)。

于 2012-08-15T06:12:22.207 回答