Существует ли программный способ определения зарезервированных слов С#?

Я ищу функцию, например

public bool IsAReservedWord(string TestWord)

Я знаю, что мог бы свернуть свой собственный, захватив резервный список слов из MSDN. Тем не менее, я надеялся, что есть что-то, встроенное в язык или .NET-отражение, на которое можно положиться, поэтому мне не пришлось бы пересматривать эту функцию при переходе на более новые версии С#/. NET.

Причина, по которой я ищу это, - это поиск защиты в генерации кода файла .tt.

Ответы

Ответ 1

CSharpCodeProvider cs = new CSharpCodeProvider();
var test = cs.IsValidIdentifier("new"); // returns false
var test2 = cs.IsValidIdentifier("new1"); // returns true

Ответ 2

Microsoft.CSharp.CSharpCodeGenerator имеет метод IsKeyword(string), который делает именно это. Тем не менее, класс является внутренним, поэтому вам нужно использовать отражение для доступа к нему, и нет гарантии, что он будет доступен в будущих версиях .NET framework. Обратите внимание, что IsKeyword не заботится о разных версиях С#.

Открытый метод System.CodeDom.Compiler.ICodeGenerator.IsValidIdentifier(string) также отклоняет ключевые слова. Недостатком является то, что этот метод также выполняет некоторые другие проверки, поэтому также отклоняются и другие строки без ключевого слова.

Обновление: Если вам просто нужно создать правильный идентификатор, а не решить, является ли конкретная строка ключевым словом, вы можете использовать ICodeGenerator.CreateValidIdentifier(string). Этот метод также заботится о строках с двумя лидирующими символами подчеркивания, префикс их еще одним подчеркиванием. То же самое относится к ключевым словам. Обратите внимание, что ICodeGenerator.CreateEscapedIdentifier(string) префикс таких строк с знаком @.

Идентификаторы с двумя ведущими символами подчеркивания зарезервированы для реализации (т.е. компилятор С# и связанные с ним генераторы кода и т.д.), поэтому избегать таких идентификаторов из вашего кода, как правило, хорошая идея.

Обновление 2: Причиной предпочтения ICodeGenerator.CreateValidIdentifier over ICodeGenerator.CreateEscapedIdentifier является то, что __x и @__x являются по существу тем же самым идентификатором. Следующие команды не будут компилироваться:

int __x = 10;
int @__x = 20;

В случае, если компилятор будет генерировать и использовать идентификатор __x, и пользователь использовал бы @__x в результате для вызова CreateEscapedIdentifier, произошла ошибка компиляции. При использовании CreateValidIdentifier эта ситуация предотвращается, поскольку пользовательский идентификатор превращается в ___x (три символа подчеркивания).

Ответ 3

Однако я надеялся, что есть что-то, встроенное в язык или .NET-отражение, на которое можно положиться, поэтому мне не придется пересматривать функцию, когда я перехожу к более новым версиям С#/. NET.

Обратите внимание, что С# никогда не добавлял новое ключевое слово зарезервированное, так как v1.0. Каждое новое ключевое слово было безоговорочным контекстуальным ключевым словом.

Хотя в будущем возможно добавить новое зарезервированное ключевое слово, мы старались не делать этого.

Список всех зарезервированных и контекстных ключевых слов до С# 5 см. в

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

Ответ 4

    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;
    }

Так как определение CreateEscapedIdentifier:

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

он будет правильно идентифицировать идентификаторы __ как зарезервированные.