C# 10.0: Extended Property Patterns – Use the Dot Token to Access Nested Members

In the previous blog posts you learned about different C# 10.0 features:

In this blog post, let’s look at another interesting feature of C# 10.0 which is called extended property patterns.

Property Patterns in C# 9.0

I’ve written a bigger blog post about pattern matching in C# 9.0. If you’re not familiar with pattern matching, I recommend you to read that blog post.

In that blog post, we created a class hierarchy like you see it below. As you can see, there is a Person class, and the two classes Developer and Manager that inherit from Person. Note also that the Developer class has a Manager property of type Manager.

public class Person
{
  public string? FirstName { get; set; }
  public int YearOfBirth { get; set; }
}
public class Developer : Person
{
  public Manager? Manager { get; set; }
}
public class Manager : Person
{
}

If you want to check if a variable contains a Developer instance that has a Manager with the firstname Thomas, you can do that in C# 9.0 as below:

if (obj is Developer { Manager: { FirstName: "Thomas" } } developerWithThomasAsManager)
{
  // Use the developerWithThomasAsManager variable here
}

Extended Property Patterns in C# 10.0

In C# 10.0, you can use the . token to access members in a property pattern. This is called extended property patterns. The code snippet below uses the . token to check if the Manager‘s FirstName property contains the value Thomas. This means that the code snippet below does exactly the same as the code snippet above.

if (obj is Developer { Manager.FirstName: "Thomas" } developerWithThomasAsManager)
{
  // Use the developerWithThomasAsManager variable here
}

Important to mention is that if the Manager property of the Developer instance is null, you do not get a NullReferenceException. You could think that you get one, because you wrote Manager.FirstName. But remember, you’re writing a pattern here to check the shape of the object, you’re not directly accessing that property with your code, so there won’t be a NullReferenceException. That means if the Manager property is null, the pattern { Manager.FirstName: "Thomas" } does not match, and the condition of the if statement above evaluates to false, and the if block is not entered. That’s it.

The More Nesting You Have, the Greater This Feature Is

Let’s say you want to check if the Manager‘s firstname has a length of 6. In C# 9.0 you do this by nesting property patterns to access the Length property of the string type, which is the type of the FirstName property. You see this in the code snippet below:

if (obj is Developer { Manager: { FirstName: { Length: 6 } } } developerWithManagerFirstnameLengthOfSix)
{
  // Use the developerWithManagerFirstnameLengthOfSix variable here
}

In the next code snippet you see the C# 10.0 way to check if a developer’s manager has a firstname with a length of 6. The extended property patterns with the . token make this super easy to read:

if (obj is Developer { Manager.FirstName.Length: 6 } developerWithManagerFirstnameLengthOfSix)
{
  // Use the developerWithManagerFirstnameLengthOfSix variable here
}

Use Multiple Extended Property Patterns

You can also use multiple extended property patterns. What if you want to check for example if a developer has a manager who has a firstname with a length of 6 and who (=the manager) is born in 1980? Below you see the C# 9.0 way to do this:

if (obj is Developer { Manager: { FirstName: { Length: 6 }, YearOfBirth: 1980 } } dev)
{
  // Use the dev variable here
}

In C# 10.0, you can write the same code as below with an extended property pattern to access the Length property of the manager’s firstname:

if (obj is Developer { Manager: { FirstName.Length: 6, YearOfBirth: 1980 } } dev)
{
    // Use the dev variable here
}

You can even go further in C# 10.0 and use the . token also to access the Manager‘s FirstName and YearOfBirth properties like you see it in the code snippet below:

if (obj is Developer { Manager.FirstName.Length: 6, Manager.YearOfBirth: 1980 } dev)
{
  // Use the dev variable here
}

Personally, I am a fan of the very last code snippet here, because when I read it, I recognize very fast that the pattern checks the properties FirstName and YearOfBirth of the Manager, and not those of the Developer. So, using the . token can increase readability.

Summary

As you saw in this blog post, extended property patterns are a little C# 10.0 language extension that let’s you use the . token to access nested properties when you use a property pattern. As mentioned at the beginning of this blog post, if you’re not familiar with pattern matching in C#, my blog post about pattern matching in C# 9.0 is a good read.

Share this post

Comments (7)

  • Alexander Batishchev Reply

    I wonder how come anyone finds either option (the existing and the updated) anywhere elegant, usable, or permissible. In my opinion this is horrible, I’ll never let it into a codebase I curate.
    Especially the part where operator == is replaced by : (and nowhere else in the language).

    October 24, 2021 at 5:57 pm
    • Mel Grubb Reply

      I think you’re looking at it wrong. Don’t think of it as an expression. Think of it as a chunk of JSON. This code:

      { Manager: { FirstName.Length: 6, YearOfBirth: 1980 } }

      Is kind of like an anonymous object, described in JSON. This object’s Manager property has a FirstName whose length is 6, and a YearOfBirth property with the value 1980. You’re saying you want the developers that look more or less like this. The fact that they’ve sort of cheated the syntax into something that’s pseudo-json-ish to save space is a good thing. No-one ever said you HAD to use the pattern matching syntax, just that you can accomplish the same thin in less space if you do.

      November 6, 2021 at 4:07 pm
      • Thomas Claudius Huber Reply

        Thanks for the fantastic answer Mel. I agree 100%, thanks for the great JSON analogy. It’s exactly this!

        November 8, 2021 at 12:37 pm
      • Bill Reply

        “Think of it as a chunk of JSON. … kind of like an anonymous object”

        If a strongly typed language uses a “chunk of JSON” to save a few explicit commands, at the cost of semantic confusion, and inconsistency, is it still a strongly typed language ? If so, why not shoehorn Lisp, or APL,, chunks into C# ?

        ” you want the developers” In this case you “want” to test a single instance of ‘developer for matching field values. Under the hood, you are using a method that tests two fields, and uses logical ‘And.

        February 3, 2022 at 11:22 am
  • jT Reply

    pity,

    Developer developer = new () { Manager.FirstName.Length: 6, Manager.YearOfBirth: 1980 }

    NOT work

    December 2, 2021 at 7:24 pm
    • Thomas Claudius Huber Reply

      Yeah, as that would be an object initialization and not a pattern to test. :)
      It cannot work, as for example Length is a readonly property of the string type, and so setting Manager.FirstName.Length:6 makes no sense. Manager.FirstName=”something” could make sense, but who creates the Manager object then? I think there are many questions to answer before we get a syntax like this. With structs instead of classes we could come close to it. But maybe instead of doing that, this is what constructors are made for.

      December 13, 2021 at 2:18 pm
  • Bill Reply

    if (obj is Developer { Manager.FirstName.Length: 6, Manager.YearOfBirth: 1980 } dev)
    {
    // Use the dev variable here
    }

    imho, the “hidden” assignment to ‘dev … which does not require explicit type declaration … is obscure, and violates the strongly typed nature of C#. Yes, structurally, there is nesting in this example, but that obfuscates what is happening which is a logical ‘And of two conditions.

    This kind of “black box” embodying “spooky action at a distance” is a potential source of confusion.

    February 3, 2022 at 10:46 am

Leave a Reply

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

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.