0

When indexing into an IEnumerable, I've noticed that using an index that is out of range will result in a default value being returned. I would have expected to receive an ArgumentOutOfRangeException. For example, this code results in listItem being 0. No exception is thrown.

Dim list As IEnumerable = New List(Of Integer)({1, 2, 3})
Dim listItem As Integer = CInt(list(-1))

If I cast as an IList, I get the ArgumentOutOfRangeException as expected.

This code throws the exception.

Dim list As IList = New List(Of Integer)({1, 2, 3})
Dim listItem As Integer = CInt(list(-1))

The fact that I can index into IEnumerable is surprising in it of itself. I'm sure it's using Linq extensions, but I cannot figure out which is in use. The behavior seems to indicate the ElementAtOrDefault method is being used, but I cannot find any documentation to support this.

What's going on here? Is there a good way to figure out which methods are actually in use?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Jason Tyler
  • 1,331
  • 13
  • 26
  • I just found the more formal explanation here [Why can I access an item in KeyCollection/ValueCollection by index even if it doesn't implement IList(Of Key)?](http://stackoverflow.com/questions/36933428/why-can-i-access-an-item-in-keycollection-valuecollection-by-index-even-if-it-do) – sstan May 27 '16 at 20:21

1 Answers1

1

You are correct. It's doing some compiler magic and converting that to a call to Enumerable.ElementAtOrDefault as you suspected.

I confirmed by compiling your code in VB.NET, and then using a decompiler tool to see the equivalent code in C#.

EDIT

I just found another SO post that explains this behavior with references to the specification. Marked as a duplicate.

Community
  • 1
  • 1
sstan
  • 35,425
  • 6
  • 48
  • 66