Introduction
This post was inspired by this post by Damian Guard “8 things you probably didn’t know about C#”
The first point is that indexers can take params as a parameter so you can then give a list of items to get another list of items using the indexer.
Default properties and indexers
Lets take this collection as an example of how an indexer works.
Dim _list = New List(of String) From {"test1", "test2"}```
An indexer let’s you do this.
```vbnet
_list(0)```
This is exactly the same thing as
```vbnet
_list.Item(0)```
When we look at the collection and the item property this would look something like this.
Default Public Property Item(index As Integer) As String Get ‘ Code here End Get Set(value As String) ‘ Code here End Set End Property``` The Default keyword is the key here. It determines which property is the indexer and which you can use without specifying it’s name.
But you can use this in your normal classes to.
Just look at this example.
Imports System.Reflection
Module Module1
Sub Main()
Dim s As New SomeCollection
Console.WriteLine(s(0))
For Each s1 In s({0, 1, 2})
Console.WriteLine(s1)
Next
Console.ReadLine()
End Sub
Public Class SomeCollection
Private _list As IList(Of String)
Public Sub New()
_list = New List(Of String) From {"test1", "test2", "test3", "test4"}
End Sub
Default Public ReadOnly Property Item(index As Integer) As String
Get
Return _list(index)
End Get
End Property
Default Public ReadOnly Iterator Property Item(index() As Integer) As IEnumerable(Of String)
Get
For Each i In index
Yield _list(i)
Next
End Get
End Property
End Class
End Module
So I can use instance(0) to get one element or use instance({0,2}) to get a list of elements.
But I can also add more possibilities.
Imports System.Reflection
Module Module1
Sub Main()
Dim s As New SomeCollection
For Each s1 In s({"test1", "test3"})
Console.WriteLine(s1)
Next
Console.WriteLine(s("test1"))
Console.ReadLine()
End Sub
Public Class SomeCollection
Private _list As IList(Of String)
Public Sub New()
_list = New List(Of String) From {"test1", "test2", "test3", "test4"}
End Sub
Default Public ReadOnly Property Item(index As Integer) As String
Get
Return _list(index)
End Get
End Property
Default Public ReadOnly Property Item(index As String) As Integer
Get
Return _list.IndexOf(index)
End Get
End Property
Default Public ReadOnly Iterator Property Item(index() As String) As IEnumerable(Of Integer)
Get
For Each i In index
Yield _list.IndexOf(i)
Next
End Get
End Property
End Class
End Module
I now use a string as the indexer. I could even combine the integer and the string one in one class. And so much more.
This is the whole thing combined and in C#.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var s = new SomeCollection();
Console.WriteLine(s[0]);
foreach(var s1 in s[0,1,2])
{
Console.WriteLine(s1);
}
Console.WriteLine(s["test1"]);
foreach (var s1 in s["test1", "test3"])
{
Console.WriteLine(s1);
}
Console.ReadLine();
}
}
public class SomeCollection
{
private IList<String> _list;
public SomeCollection()
{
_list = new List<String> {"test1", "test2", "test3", "test4"};
}
public String this[int index]
{
get { return _list[index]; }
}
public int this[String index]
{
get { return _list.IndexOf(index); }
}
public IEnumerable<String> this[params int[] index]
{
get { return index.Select(i => _list[i]); }
}
public IEnumerable<int> this[params String[] index]
{
get { return index.Select(i => _list.IndexOf(i)); }
}
}
}
And we see that in C# they use params. in VB.Net this is however not an option.
If you try this.
vbnet
Default Public ReadOnly Iterator Property Item(ParamArray index() As String) As IEnumerable(Of Integer)
Get
For Each i In index
Yield _list.IndexOf(i)
Next
End Get
End Property
Then you will get an error stating.
Properties with no required parameters cannot be declared ‘Default’.
Conclusion
The default property looks very different in VB.Net then it is in C# but it is there. And I’m sure not to many of used it in the last year.