views:

7142

answers:

7

DataGridView, for example, lets you do this:

DataGridView dgv = ...;
DataGridViewCell cell = dgv[1,5];

but for the life of me I can't find the documentation on the index/square-bracket operator. What do they call it? Where is it implemented? Can it throw? How can I do the same thing in my own classes?

ETA: Thanks for all the quick answers. Briefly: the relevant documentation is under the "Item" property; the way to overload is by declaring a property like public object this[int x, int y]{ get{...}; set{...} }; the indexer for DataGridView does not throw, at least according to the documentation. It doesn't mention what happens if you supply invalid coordinates.

ETA Again: OK, even though the documentation makes no mention of it (naughty Microsoft!), it turns out that the indexer for DataGridView will in fact throw an ArgumentOutOfRangeException if you supply it with invalid coordinates. Fair warning.

+2  A: 
Operators                           Overloadability

+, -, *, /, %, &, |, <<, >>         All C# binary operators can be overloaded.

+, -, !,  ~, ++, --, true, false    All C# unary operators can be overloaded.

==, !=, <, >, <= , >=               All relational operators can be overloaded, 
         but only as pairs.

&&, ||        They can't be overloaded

() (Conversion operator)     They can't be overloaded

+=, -=, *=, /=, %=                  These compound assignment operators can be 
         overloaded. But in C#, these operators are
         automatically overloaded when the respective
         binary operator is overloaded.

=, . , ?:, ->, new, is, as, sizeof  These operators can't be overloaded

    [ ]                             Can be overloaded but not always!

Source of the information

For bracket:

public Object this[int index]
{

}

BUT

The array indexing operator cannot be overloaded; however, types can define indexers, properties that take one or more parameters. Indexer parameters are enclosed in square brackets, just like array indices, but indexer parameters can be declared to be of any type (unlike array indices, which must be integral).

From MSDN

Daok
i don't see `[]` on the list
jjnguy
It's at the bottom.
Ryan Thames
yes it can be overloaded, as long as the parameter signature is different, exactly like any other method's overloading restrictions
Charles Bretana
It can, but not for the condition I wrote. It's from MSDN. Check the source if you do not believe me
Daok
Sorry if I misread your post, but what condition are you referring to?
Charles Bretana
+9  A: 
public class CustomCollection : List<Object>
{
    public Object this[int index]
    {
        // ...
    }
}
Jason Miesionczek
Actually, this is really dangerous - you now have two competing implementations: anyone with a variable typed as List<T> or IList<T> or IList etc won't execute your custom code.
Marc Gravell
Agreed -- if nothing else, it's not necessary to derive your CustomCollection from List, but I hadn't realized it was actually dangerous
Coderer
+33  A: 

Hi, you can find how to do it here. In short it is:

public object this[int i]
{
    get { return InnerList[i]; }
    set { InnerList[i] = value; }
}
Ruben
+4  A: 

That would be the item property: http://msdn.microsoft.com/en-us/library/0ebtbkkc.aspx

Maybe something like this would work:

public T Item[int index, int y]
{ 
    //Then do whatever you need to return/set here.
    get; set; 
}
Ricardo Villamil
Thanks a lot! If I could set two answers, I'd add yours as well -- nobody else knew to look for Item in the documentation...
Coderer
In terms of how it gets implemented, it is "Item", but in C# terms, it is "this"
Marc Gravell
Right, but I asked "for the life of me I can't find the documentation on the index/square-bracket operator" -- I meant when you look up a library class in MSDN, where do they tell you about the operator? That's why I made that last "ETA" about what it throws -- the docs are *wrong*.
Coderer
+1  A: 

Here is an example returning a value from an internal List object. Should give you the idea.

  public object this[int index]
  {
     get { return ( List[index] ); }
     set { List[index] = value; }
  }
Rob Prouse
+1  A: 

If you mean the array indexer,, You overload that just by writing an indexer property.. And you can overload, (write as many as you want) indexer properties as long as each one has a different parameter signature

public class EmpployeeCollection: List<Employee>
{
    public Employee this[int employeeId]
    {   
        get 
        { 
            foreach(Employee emp in this)
                if (emp.EmployeeId == employeeId) return emp;
            return null;
        }
    }
    public Employee this[string employeeName]        {   
        get 
        { 
            foreach(Employee emp in this)
                if (emp.name == employeeName) return emp;
            return null;
        }
    }

}
Charles Bretana
First, you mean this[], not this() - however, providing a custom (but different) this[int] on something that is a list (IList/IList<T>/List<T>) is quite dangerous - and could lead to subtle bugs between the "int index" and "int employeeId" versions. Both are still callable.
Marc Gravell
Yes, thanks for catch... I've edited to correct that...
Charles Bretana
and in fact, I don;t think the code I entered above would compile without adding a new or override statement precisely because of the existence of the List<T> implementation of this[int]. You're right about the potential when doing this, simply meant it as example of overloading indexer.
Charles Bretana
+1  A: 

For CLI C++ (compiled with /clr) see this MSDN link.

In short, a property can be given the name "default":

ref class Class
{
 public:
  property System::String^ default[int i]
  {
    System::String^ get(int i) { return "hello world"; }
  }
};