2

我想声明一个通用的对象集合,并能够通过索引器通过键字符串值或索引来访问它们。我该怎么做呢?是否有一个开箱即用的 .Net 类不需要子类化?

class Program
{

    static void Main(string[] args)
    {

        System.Collections.Generic.WhatKindOfCollection<PageTab> myPageTabs 
            = new System.Collections.Generic.WhatKindOfCollection<PageTab>();

        PageTab pageTab1 = new PageTab();
        pageTab1.ID = "tab1";
        myPageTabs.Add(pageTab1);

        myPageTabs.Add(new PageTab("tab2"));

        myPageTabs[0].label = "First Tab";
        myPageTabs["tab2"].label = "Second Tab";

    }

    public class PageTab
    {
        public PageTab(string id)
        {
            this.ID = id;
        }

        public PageTab() { }


        //Can I define ID to get the key property by default?
        public string ID { get; set; }

        public string label { get; set; }
        public bool visible { get; set; }
    }
}
4

3 回答 3

3

看起来您正在寻找从System.Collections.ObjectModel.KeyedCollections派生的东西。

我认为您要查找的特定类不存在于 .NET 框架中,因此您可能必须自己对其进行子类化。

KeyedCollection 是对象的基类,其中键是对象的一部分。这意味着当您使用整数索引访问它时,您将取回原始对象而不是 KeyValueCollection。

我已经有一段时间没有使用它了,但我不记得它太难了。

编辑:您的另一个代码选项。这比我记得的要容易:

public class MyKeyedCollection<TKey, TItem> : KeyedCollection<TKey, TItem>
{
    public MyKeyedCollection(Func<TItem, TKey> keyFunction)
    {
        _keyFunction = keyFunction;
    }

    private Func<TItem, TKey> _keyFunction;

    protected override TKey GetKeyForItem(TItem item)
    {
        return _keyFunction(item);
    }
}

要使用:

var myPageTabs = new MyKeyedCollection<String, PageTab>(i => i.ID);

或预LINQ:

public class MyKeyedCollection<TKey, TItem> : KeyedCollection<TKey, TItem>
{
    public MyKeyedCollection(String keyProperty)
    {
        _keyProperty = keyProperty;
    }

    private String _keyProperty;

    protected override TKey GetKeyForItem(TItem item)
    {
        return (TKey)item.GetType().GetProperty(_keyProperty).GetValue(item, null);
    }
}

MyKeyedCollection<String, PageTab> myPageTabs = new MyKeyedCollection<String, PageTab>("ID");
于 2012-08-17T01:24:10.870 回答
2

这实际上是OrderedDictionary类。但是,不幸的是,它不是泛型类,因此您必须包含强制转换,或者将其包装在您自己的集合类型中。

基类库中没有通用等效KeyedCollection<T,U>项,但提供了基类基础结构来实现您自己的版本。

最简单的选择就是维护两个集合 - aDictionary<string, PageTab>和 a List<PageTab>。创建项目时,您可以将其添加到两个集合中,并通过相应的集合进行访问。因为PageTab是一个类,所以额外的开销是最小的(因为你只是存储对象引用)。这也可以很容易地包装到一个类中:

public class IndexedDictionary<T, U>
{
    private Dictionary<T,U> dictionary = new Dictionary<T,U>();
    private List<U> list = new List<U>();

    public void Add(T key, U value)
    {
        list.Add(value);
        dictionary.Add(key, value);
    }

    public U this[int index]
    {
       get { return list[index]; }
    }
    public U this[T key]
    {
       get { return dictionary[key]; }
    }
}

当然,您可能还希望实现一些适当的接口(例如IEnumerable<U>),但以上内容将实现您在问题中列出的目标。

于 2012-08-17T01:21:03.427 回答
0

你为什么不用字典?

Dictionary<string, PageTab> myDictionary = new Dictionary<string, PageTab>();
myDictionary.Add("tab1", new PageTab("tab1"));
PageTab myPageTab = myDictionary["tab1"];

编辑 为了避免键入两次键(一次作为字典键,一次在构造函数中),您可以扩展字典。在命名空间的顶层创建以下类:

public static class Extensions
{
    public static void AddPageTab(this Dictionary<string, PageTab> mydict, PageTab pt)
    {
        mydict.Add(pt.ID, pt);
    }
}

你调用简单的添加 PageTab 是这样的:

myDictionary.AddPageTab(new PageTab("tab1"));
于 2012-08-17T01:19:30.280 回答