Living .NET...

Musings on .NET, and the like - Manoj G [MVP, Connected Systems Developer]

Indexer Insights

We all know that types, including interfaces can have a default property. Default properties are used as a short-hand notation for accessing items in an array/collection of objects contained within the object. For e.g. Item is the default property of an ArrayList (for that matter, IList.Item) which gets the object stored in the specified index. For eg :

Dim arrItems As New ArrayList
Console.WriteLine(
CType(arrItems(0), String))
'Equivalent to this
'Console.WriteLine(CType(arrItems.Item(0), String))

In C#, default properties are called Indexers. There is a subtle difference in the way indexers are declared in VB.NET and C#. Here's an example (MSDN):

' Visual Basic
' A class that contains many Widgets
Public Class Widgets
    
'Default property implementation
    
Default Public Property Widget(ByVal As IntegerAs Widget
        
Get
        
        
' Implementation code to return a widget goes here.
        
        
End Get
        
        Set
(ByVal Value As Widget)
        
        
' Implementation code to set a widget goes here.
        
        
End Set
    End Property
End Class

// C#
// Class that contains many Widgets.
public class Widgets 
{
    
// Indexer implementation.
    
public Widget this[int index] 
    {    
        
get 
        
{
            
// Insert code to return a Widget.
        
}
    
        
set 
        
{
            
// Insert code to set a Widget.
        
}
    }
}

If you notice, there is no provision to specify the name of the Indexer in C#, as present in VB.NET. In C#, the name defaults to "Item". However, you can specify a name by means of an attribute as shown below:

[System.Runtime.CompilerServices.CSharp.IndexerName("Widget")]
public int this [int index] {  }

Here are some other aspects of an Indexer we need to know:

1. You can have only one Default property/Indexer per class. The Indexer, however, can be overloaded.

2. Default properties should accept parameters. We cannot have VB6 like (parameterless) properties. Refer to this link for Property changes in VB.NET as compared to VB.

Finally, a tip to end this note on indexers; a frequently asked question in the newsgroups. If we need to find out programmatically, if a class has an indexer, we can query a custom attribute called DefaultMemberAttribute attribute using Reflection as shown below:

static bool CheckIfIndexerPresent(Object obj) 
{
    
object[] oAttributes = obj.GetType().GetCustomAttributes(true); 
    
for(short j = 0; j < oAttributes.Length; j++) 
    {
        
if (oAttributes[j] is DefaultMemberAttribute)
        {
            
return true;
        }
    } 
    
return false;
}
Posted: Oct 15 2004, 05:29 PM by Manoj G | with 3 comment(s)
Filed under:

Comments

Manoj G said:

nice but i want to know how index is invoked
# December 10, 2004 6:38 PM

Manoj G said:

Can indexer declarationion take parameter other than int.
Can we write like this?
public int this [string index] {

}

What properies of arrary does indexer support?

# December 23, 2004 3:59 PM

Manoj G said:

Thanks for the lines:

...you can specify a name by means of an attribute as shown below:

[System.Runtime.CompilerServices.CSharp.IndexerName("Widget")]


I'm new to C# and still finding my way around :-)
I'd like to have the option to use either syntax:
Collection.Item(counter).Name
or
Collection[counter].Name

but after I'd added the indexer the complier kept on complaining that my code already contains a definition for 'Item'.
I added the attribute:

[System.Runtime.CompilerServices.IndexerName("Widget")]

and they were both able to co-exist.

Thanks again
# May 12, 2005 8:29 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)