LRN Quick Tips – Working with nameof

The nameof operator has gone through five iterations as the Roslyn team worked to nail down its syntax and semantics. Now that the design of the nameof operator has been finalized, we can look at some simple examples.

Within C#, nameof is a contextual keyword. This means there is no way to distinguish the nameof keyword from a call to a method that happens to be named nameof.

Lucian Wischik elaborates:

In C#, nameof is stored in a normal InvocationExpressionSyntax node with a single argument. That is because in C# ‘nameof’ is a contextual keyword, which will only become the “nameof” operator if it doesn’t already bind to a programmatic symbol named “nameof”

Identifying nameof Expressions

This means we can only identify nameof expressions at the semantic level. We do so by finding all invocations to “nameof” that do not bind to any symbol. These invocations must also be standalone (ie. not part of a member access like MyClass.nameof())

As with all contextual keywords, it’s a bit of a pain to work with. But that’s the price we pay for backwards compatability.

Creating a nameof expression

Previous versions of the Roslyn API allowed for direct creation of a NameOfExpressionSyntax. Now we must create an InvocationExpressionSyntax with the identifer “nameof”.

For example, we can generate the following nameof expression:

string result = nameof(result);

Side Note: As a mere mortal, I have no idea how to work with the SyntaxFactory API. I generated the above code with Kirill Osenkov’s fantastic Roslyn Quoter tool.

The important takeaway is that (at the syntax level) nameof expressions are no different than regular invocations.

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

4 Responses to LRN Quick Tips – Working with nameof

  1. nmgafter says:

    Is anything ever final?

    Should this work?

    var x = nameof(x);

    • Paulo Morgado says:

      Well. it could.

      The problem here is that x is being recursively defined. Same as Func f = n => n > 1 ? n * f(n – 1) : 1;

      On the other hand, the value of namoeof(x) is taken from the source code and not the metadata. No matter what the type of x is, nameof(x) will always be “x”. x might not even exist. As long as the syntax was valid, it would work. But it would not be a valid expression, which nameof requires.

  2. joshvarty says:

    >Is anything ever final?

    No definitely not. But my impression was that the spec had been (mostly) decided on for C# 6.

    >Should this work?
    >var x = nameof(x);

    Well I certainly thought so. 🙂 I actually opened the issue proposing that very change: https://github.com/dotnet/roslyn/issues/766

  3. Wellczech says:

    First of all, thanks for entire LRN series. It helped me a lot.

    In the last code snippet in this post, you are showing how to generate `nameof` expression via SyntaxFactory. It seems to be correct up util the point you try to read diagnostics from compilation or `SemanticModel`. You’ll immediately get:
    “Error CS0103: The name ‘nameof’ does not exist in the current context”

    That is, because you need to explicitly mark the “nameof” identifier token as a contextual `nameof` keyword. Otherwise Roslyn will never try to bind the name as the keyword.

    SyntaxFactory.Identifier
    (
    SyntaxFactory.TriviaList(),
    SyntaxKind.NameOfKeyword,
    “nameof”,
    “nameof”,
    SyntaxFactory.TriviaList()
    )

    More on why and how to do that is here:
    https://stackoverflow.com/q/46259039/1560190

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s