C# Strings with Ranges, and Indexes

This blog post is part of Third C# Annual Advent organized by Matt Groves, Developer Advocate Couchbase and Microsoft MVP. Thanks to Matt for giving me an opportunity to participate again this year. You can follow the C# Advent here.

C# 8 introduced the ability to access subsets of collections with range operators. Frequently, ranges are used to access arrays or spans, but they can also be used to access the characters inside a string. This can be especially useful if you know there are fixed length portions of text within the string you are manipulating.

For example, let’s say that you wanted to get the first eight characters of a file name. You could use the Substring method on the string class. Or you could use a range operator to get the first eight characters.

[TestMethod]
public void GetTheFirstEightCharactersOfAString()
{
    string fileName = "myTestFileName.txt";
    string firstEight = fileName[0..8];
    Assert.AreEqual("myTestFi"firstEight);
}

Because the range starts at the beginning of the collection of characters in the string, the first 0 in the range is optional. You could achieve the same this by leaving it out.

[TestMethod]
public void GetTheFirstEightCharactersOfAString_Shorter()
{
    string fileName = "myTestFileName.txt";
    string firstEight = fileName[..8];
    Assert.AreEqual("myTestFi"firstEight);
}

What would be more likely is that you would want to get the file name without the extension. Assuming that you know with certainty that the file extension will always be three characters, you could define a range the starts at the beginning of the string and ends four characters from the end. You do this by using the caret to indicate that an index counts from the back of the collection. So a range of [0..^4] would retrieve all but the last for characters, which in this case would be the file name without “.txt”.

[TestMethod]
public void GetTheFileNameWithoutTheExtension()
{
    string fileName = "myTestFileName.txt";
    string fileNameWithExtension = fileName[0..^4];
    Assert.AreEqual("myTestFileName"fileNameWithExtension);
}

If you wanted to only get the file extension, you could define a range in which both indexes in the range count from the back. A range defined from ^3 to ^0 would get the last three characters in the string. Assuming again that you know that the extension is three characters, this would get the extension.

[TestMethod]
public void GetTheExtension()
{
    string fileName = "myTestFileName.txt";
    string extension = fileName[^3..^0];
    Assert.AreEqual("txt"extension);
}

In the same way that we can omit the number for the beginning of the range if the range starts at the beginning of the collection, we can omit the number at the end of the range if the range ends at the end of the collection. This code would also retrieve the extension of the file, but is slightly shorter.

[TestMethod]
public void GetTheExtension_Shorter()
{
    string fileName = "myTestFileName.txt";
    string extension = fileName[^3..];
    Assert.AreEqual("txt"extension);
}

Lets say that you have a string that is wrapped in curly braces and you only want the text inside the braces. You could easily define a range that leaves off the first and last character of the string.

[TestMethod]
public void GetTextInsideOfBrackets()
{
    string data = "{importantData}";
    string innerData = data[1..^1];
    Assert.AreEqual("importantData"innerData);
}

Using the range operators to access substring of strings doesn’t radically shift the paradigm of your code. But it does make it easier to do some of the operations that we have to write on regular basis. If you have any good examples of how you have used ranges to work with strings, please let me know in the comments below.

It you want to play with the code from this post, you can find it here.

December 21, 2019 |
Tags : CSharp

Comments Section

Feel free to comment on the post but keep it clean and on topic.

comments powered by Disqus

About Me

Eric Potter My name is Eric Potter. I have an amazing wife and 5 wonderful children. I am a Microsoft MVP for .Net. I am a software architect for Aptera Software in Ft. Wayne Indiana and an adjunct professor for Indiana Tech. I am a humble toolsmith.

Microsoft MVP Award

pottereric.github.com