views:

196

answers:

5

Is it possible to create a list that can be access by either an index or a key?

I am looking for a Collection type that already exists but has this facility, I want to avoid redefining the indexers

A: 

You can add an indexer by adding the following property to your collection:

public object this[int index]
{
    get { /* return the specified index here */ }
    set { /* set the specified index to value here */ }
}

This can be quickly added in Visual Studio by typing indexer and pressing [tab] [tab].

The return type and indexer type can be changed ofcourse. You can also add multiple indexer types.

Robert Wagner
A: 
public object this[int index]
{
    get { ... }
    set { ... }
}

As well as doing just an integer index, you can provide a key of any other type you like

public object this[String key]
{
    get { ... }
    set { ... }
}

If you don't want to define your own collection, just inherit from List<T>, or just use a variable of type List<T>.

Mark Ingram
A: 

System.Collections.Specialized.NameValueCollection can do this, but it can only store strings as values.

    System.Collections.Specialized.NameValueCollection k = 
        new System.Collections.Specialized.NameValueCollection();

    k.Add("B", "Brown");
    k.Add("G", "Green");

    Console.WriteLine(k[0]);    // Writes Brown
    Console.WriteLine(k["G"]);  // Writes Green
Martin Brown
+1  A: 

Existing answers already show how to add your own indexers.

You might want to look at some of the existing key-based collections, such as SortedList<,>, which acts similarly to Dictionary<,>, but allows key and position indexer usage.

Also - you should be able to use inheritance for much of this type of thing - for example, inheriting from Collection<> or List<>. Note that if your collection implements IList/IList<T>, I don't recommend the following (which I see occasionally):

public SomeType this[int someId] {...}

The point is, people expect the integer indexer of an IList[<T>] to be positional.

Marc Gravell
+1  A: 

There's a similar question at http://stackoverflow.com/questions/137753/what-is-the-best-data-structure-in-net-for-look-up-by-string-key-or-numeric-ind.

Have a look at KeyedCollection:

class IndexableDictionary<TKey, TItem> : KeyedCollection<TKey, TItem>
 { Dictionary<TItem, TKey> keys = new Dictionary<TItem, TKey>();

   protected override TKey GetKeyForItem(TItem item) { return keys[item];}

   public void Add(TKey key, TItem item) 
    { keys[item] = key;
      this.Add(item);
    }
 }
Mark Cidade