1

All, I have come across the following property and object declaration. The first returns an interface, and the second I am not too sure about

public IConfig this[int index]
{
    get { return (IConfig)configList[index]; }
}

object IList.this[int index]
{
    get { return configList[index]; }
    set {  }
}

I have never seen this type of declaration, namely the public IConfig this[int index] with square brackets and the odd use of this and object IList.this[int index]. Can some one explain the two notations?

I have attempted to look in the books I have, and use Google but I am unsure what I am searching for. Thanks for your time.

Edit. These are in a class that inherits as follows

public class ConfigCollection : ICollection, IEnumerable, IList
{
    ....
}
MoonKnight
  • 23,214
  • 40
  • 145
  • 277
  • 12
    That's an [indexer](http://msdn.microsoft.com/en-us/library/2549tw02.aspx) and an [explicit interface implemenation](http://msdn.microsoft.com/en-us/library/ms173157.aspx) (of an indexer) respectively. – millimoose Nov 02 '12 at 17:19
  • 1
    object is to denote that any type could be used to return from the property. Square brackets are often associated with Arrays, Dictionaries and other collection types. – JB King Nov 02 '12 at 17:21
  • 2
    The idea was to make a "list-like" object, but one that lets you retrieve items type-safely. The explicit interface implementation is there to, effectively, "hide" the non-type-safe indexer unless it's needed. – millimoose Nov 02 '12 at 17:23

3 Answers3

12

It is called an indexer and allows you to do instance[1]; when getting an element from your object. You can have a look at this answer on implementing IList as a reference

Community
  • 1
  • 1
Johan Larsson
  • 17,112
  • 9
  • 74
  • 88
3

I also want to add one more detail to Johan's post - you actually have 2 indexers going on in that class because of the multiple interfaces.

The indexer that is implemented from IList is being declared explicitly, hence this one will not be invoked by default. If you want to use the IList version of the indexer, you would need to do this:

ConfigCollection thisCollection = GetCollectionItems();

// this invokes the IList.this indexer....
var firstItem = ((IList)thisCollection)[0];  

// this invokes the other indexer
var firstItemAsIConfig = thisCollection[0];

I think the IList.this indexer is redundant, based on the code you've shared with us.

code4life
  • 15,655
  • 7
  • 50
  • 82
1

Say you had

public class MyAggregate
{
  private List<String> _things;
  public MyAggregate()
  {
    _things = new List<String>();
  }
}

So you could add

public String GetItem(int argIndex)
{
  return _things[argIndex];
}

and

public void SetItem(int argIndex, String argValue)
{
  _things[argIndex] = argValue;
}

and then access through myAggregate.GetItem(0) to get it and myAggregate.SetItem(0,"Thing") to set it.

or you could add

public string this[int argIndex] 
{
  get {return _things[argIndex];}
  set { _things[argIndex] = value;}
}

and access it through myAggregate[0] to get it and myAggregate[0] = "Thing" to set it.

The latter tends to feel more natural and you don't have to come up with two method names every time.

Tony Hopkinson
  • 20,172
  • 3
  • 31
  • 39