NDepend

Improve your .NET code quality with NDepend

C# Index and Range Operators Explained

C#8 added the index ^ and range .. operators. In this post I am attempting to demystify both in the most comprehensive way.

The index operator ^

Let’s start with the index ^ operator:

If you are used to regular expression (regex) this syntax is a bit misleading. In C# the ^ operator means index-from-the-end while in regex the character ^ matches the starting position within the string.

The range operator ..

The range operator .. is used to make a slice of the collection.

Just make sure to keep in mind that:

  • start of the range is inclusive
  • end of the range is exclusive

If you’ve been studied mathematic this syntax is a bit misleading. The C# syntax [1..4] translates to this math notation[1..4[.

Mixing index and range operators

Both operators can be mixed within the same expression:

What’s behind the index ^ operator syntactic sugar?

Actually the C# compiler translates these operators to the structures System.Index and System.Range introduced with .NET Core 3.0. These structures are also provided by .NET Standard 2.1 but not .NET Standard 2.0. It means that you cannot use this syntax within your .NET Framework projects nor .NET Core 1.0 … 2.2 projects.

Here is what the compiler does for the index syntax:

In simple cases the C# compiler doesn’t need the Index structure and can do the indexing-from-the-end work in IL.

CSharp Compiler Optimization with Index
CSharp Compiler Optimization with Index

What’s behind the range .. operator syntactic sugar?

We already mentioned the structure Range. Here is how it is used by the compiler. Notice the call to the special method T[] System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray<T>(T[] array, Range range).

Support for collections other than array

The index syntax ^ works for all collection types that have both:

  • a Count or Length property,
  • and a single integer indexer [int].

Index and Range support for mainstream collections

As we can see the index syntax ^ works with IList<T> and List<T> but not with ISet<T>, Hashset<T>, IDictionary<K,V> and Dictionary<K,V>. Those last four are not indexed collections.

The range syntax .. is more peaky and also requires the collection type to present a int[] Slice(int start, int length) method. As a consequence the range operator is not working with any of these collections while we could have expected that it works with at least IList<T> and List<T>.

Adding a Slice() method to IList<T> and List<T>collections was not an option because in many situations it is a breaking changes. Here is a reddit discussion about attempting to paliate this lack. It looks like adding a Slice() method to IList<T> with the default interface implementation syntax could have been an option that would have avoided breaking changes. I didn’t find the reason why it hasn’t been done, do you know?

Support for collections other than array

Finally here is an example of a custom collection supporting both index and range syntax:

Conclusion

Personally I need to thoroughly understand a syntactic sugar before using it, hence this post.

This new syntax is great but a bit limited due to the fact that IList<T> and List<T> don’t support range.

My dad being an early programmer in the 70's, I have been fortunate to switch from playing with Lego, to program my own micro-games, when I was still a kid. Since then I never stop programming.

I graduated in Mathematics and Software engineering. After a decade of C++ programming and consultancy, I got interested in the brand new .NET platform in 2002. I had the chance to write the best-seller book (in French) on .NET and C#, published by O'Reilly (> 15.000 copies) and also did manage some academic and professional courses on the platform and C#.

Over the years, I gained a passion for understanding structure and evolution of large complex real-world applications, and for talking with talented developers behind it. As a consequence, I got interested in static code analysis and started the project NDepend.

Today, with more than 8.000 client companies, including many of the Fortune 500 ones, NDepend offers deeper insight and understanding about their code bases to a wide range of professional users around the world.

I live with my wife and our twin babies Léna and Paul, in the beautiful island of Mauritius in the Indian Ocean.

Leave a Reply

Your email address will not be published. Required fields are marked *