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>、独自のバージョンを実装するための基本クラスインフラストラクチャを提供します。

Dictionary<string, PageTab>最も簡単な方法は、aとaの2つのコレクションを維持すること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"];

編集 キーを2回入力するのを避けるために(1回は辞書キーとして1回はコンストラクターで)、辞書を拡張できます。名前空間のトップレベルに次のクラスを作成します。

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 に答える