Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a programatic way to identify c# reserved words?

I'm looking for a function like

public bool IsAReservedWord(string TestWord)

I know I could roll my own by grabbing a reserve word list from MSDN. However I was hoping there was something built into either the language or .NET reflection that could be relied upon so I wouldn't have to revisit the function when I move to newer versions of C#/.NET.

The reason I'm looking for this is I'm looking for a safeguard in .tt file code generation.

like image 530
Aheho Avatar asked Mar 10 '11 16:03

Aheho


4 Answers

CSharpCodeProvider cs = new CSharpCodeProvider();
var test = cs.IsValidIdentifier("new"); // returns false
var test2 = cs.IsValidIdentifier("new1"); // returns true
like image 191
Bala R Avatar answered Nov 17 '22 23:11

Bala R


The Microsoft.CSharp.CSharpCodeGenerator has an IsKeyword(string) method that does exactly that. However, the class is internal, so you have to use reflection to access it and there's no guarantee it will be available in future versions of the .NET framework. Please note that IsKeyword doesn't take care of different versions of C#.

The public method System.CodeDom.Compiler.ICodeGenerator.IsValidIdentifier(string) rejects keywords as well. The drawback is this method does some other validations as well, so other non-keyword strings are also rejected.

Update: If you just need to produce a valid identifier rather than decide if a particular string is a keyword, you can use ICodeGenerator.CreateValidIdentifier(string). This method takes care of strings with two leading underscores as well by prefixing them with one more underscore. The same holds for keywords. Note that ICodeGenerator.CreateEscapedIdentifier(string) prefixes such strings with the @ sign.

Identifiers startings with two leading underscores are reserved for the implementation (i.e. the C# compiler and associated code generators etc.), so avoiding such identifiers from your code is generally a good idea.

Update 2: The reason to prefer ICodeGenerator.CreateValidIdentifier over ICodeGenerator.CreateEscapedIdentifier is that __x and @__x are essentially the same identifier. The following won't compile:

int __x = 10;
int @__x = 20;

In case the compiler would generate and use a __x identifier, and the user would use @__x as a result to a call to CreateEscapedIdentifier, a compilation error would occur. When using CreateValidIdentifier this situation is prevented, because the custom identifier is turned into ___x (three underscores).

like image 24
Ondrej Tucny Avatar answered Nov 18 '22 00:11

Ondrej Tucny


However I was hoping there was something built into either the language or .NET reflection that could be relied upon so I wouldn't have to revisit the function when I move to newer versions of C#/.NET.

Note that C# has never added a new reserved keyword since v1.0. Every new keyword has been an unreserved contextual keyword.

Though it is of course possible that we might add a new reserved keyword in the future, we have tried hard to avoid doing so.

For a list of all the reserved and contextual keywords up to C# 5, see

http://ericlippert.com/2009/05/11/reserved-and-contextual-keywords/

like image 21
Eric Lippert Avatar answered Nov 18 '22 01:11

Eric Lippert


    static System.CodeDom.Compiler.CodeDomProvider CSprovider = 
           Microsoft.CSharp.CSharpCodeProvider.CreateProvider("C#");

    public static string QuoteName(string name)
    {
        return CSprovider.CreateEscapedIdentifier(name);
    }

    public static bool IsAReservedWord(string TestWord)
    {
        return QuoteName(TestWord) != TestWord;
    }

Since the definition of CreateEscapedIdentifier is:

public string CreateEscapedIdentifier(string name)
{
    if (!IsKeyword(name) && !IsPrefixTwoUnderscore(name))
    {
        return name;
    }
    return ("@" + name);
}

it will properly identify __ identifiers as reserved.

like image 42
Gabe Avatar answered Nov 18 '22 01:11

Gabe