C#中是否有方法检查字符串是否为有效标识符
在Java中,字符类上有称为C#中是否有方法检查字符串是否为有效标识符,c#,identifier,C#,Identifier,在Java中,字符类上有称为isJavaIdentifierStart和isJavaIdentifierPart的方法,可以用来判断字符串是否是有效的Java标识符,如下所示: public boolean isJavaIdentifier(String s) { int n = s.length(); if (n==0) return false; if (!Character.isJavaIdentifierStart(s.charAt(0))) return fal
isJavaIdentifierStart
和isJavaIdentifierPart
的方法,可以用来判断字符串是否是有效的Java标识符,如下所示:
public boolean isJavaIdentifier(String s) {
int n = s.length();
if (n==0) return false;
if (!Character.isJavaIdentifierStart(s.charAt(0)))
return false;
for (int i = 1; i < n; i++)
if (!Character.isJavaIdentifierPart(s.charAt(i)))
return false;
return true;
}
public boolean isJavaIdentifier(字符串s){
int n=s.长度();
如果(n==0)返回false;
如果(!Character.isJavaIdentifierStart(s.charAt(0)))
返回false;
对于(int i=1;i
C#是否有类似的功能?这可以使用反射来完成-请参见是:
// using System.CodeDom.Compiler;
CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
if (provider.IsValidIdentifier (YOUR_VARIABLE_NAME)) {
// Valid
} else {
// Not valid
}
从这里开始:我会对这里提供的其他解决方案保持警惕。调用CodeDomProvider.CreateProvider需要查找和解析Machine.Config文件以及app.Config文件。这可能比您自己检查字符串所需的时间慢好几倍 相反,我建议您进行以下更改之一:
基本上是这样的:
const string start = @"(\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl})";
const string extend = @"(\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf})";
Regex ident = new Regex(string.Format("{0}({0}|{1})*", start, extend));
s = s.Normalize();
return ident.IsMatch(s);
最近,我编写了一个扩展方法,将字符串验证为有效的C#标识符 您可以在此处找到实施要点: 它基于标识符()的MSDN文档 在这里进行巫术 在.NET Core/DNX中,您可以使用Roslyn SyntaxFacts来完成此操作
Microsoft.CodeAnalysis.CSharp.SyntaxFacts.IsReservedKeyword(
Microsoft.CodeAnalysis.CSharp.SyntaxFacts.GetKeywordKind("protected")
);
foreach (ColumnDefinition cl in tableColumns)
{
sb.Append(@" public ");
sb.Append(cl.DOTNET_TYPE);
sb.Append(" ");
// for keywords
//if (!Microsoft.CodeAnalysis.CSharp.SyntaxFacts.IsValidIdentifier(cl.COLUMN_NAME))
if (Microsoft.CodeAnalysis.CSharp.SyntaxFacts.IsReservedKeyword(
Microsoft.CodeAnalysis.CSharp.SyntaxFacts.GetKeywordKind(cl.COLUMN_NAME)
))
sb.Append("@");
sb.Append(cl.COLUMN_NAME);
sb.Append("; // ");
sb.AppendLine(cl.SQL_TYPE);
} // Next cl
或者在使用Codedom的旧版本中-查看mono sourcecode后: CodeDomProvider.cs
public virtual bool IsValidIdentifier (string value)
286 {
287 ICodeGenerator cg = CreateGenerator ();
288 if (cg == null)
289 throw GetNotImplemented ();
290 return cg.IsValidIdentifier (value);
291 }
292
public override ICodeGenerator CreateGenerator()
91 {
92 #if NET_2_0
93 if (providerOptions != null && providerOptions.Count > 0)
94 return new Mono.CSharp.CSharpCodeGenerator (providerOptions);
95 #endif
96 return new Mono.CSharp.CSharpCodeGenerator();
97 }
然后是CSharpCodeProvider.cs
public virtual bool IsValidIdentifier (string value)
286 {
287 ICodeGenerator cg = CreateGenerator ();
288 if (cg == null)
289 throw GetNotImplemented ();
290 return cg.IsValidIdentifier (value);
291 }
292
public override ICodeGenerator CreateGenerator()
91 {
92 #if NET_2_0
93 if (providerOptions != null && providerOptions.Count > 0)
94 return new Mono.CSharp.CSharpCodeGenerator (providerOptions);
95 #endif
96 return new Mono.CSharp.CSharpCodeGenerator();
97 }
然后是CSharpCodeGenerator.cs
protected override bool IsValidIdentifier (string identifier)
{
if (identifier == null || identifier.Length == 0)
return false;
if (keywordsTable == null)
FillKeywordTable ();
if (keywordsTable.Contains (identifier))
return false;
if (!is_identifier_start_character (identifier [0]))
return false;
for (int i = 1; i < identifier.Length; i ++)
if (! is_identifier_part_character (identifier [i]))
return false;
return true;
}
private static System.Collections.Hashtable keywordsTable;
private static string[] keywords = new string[] {
"abstract","event","new","struct","as","explicit","null","switch","base","extern",
"this","false","operator","throw","break","finally","out","true",
"fixed","override","try","case","params","typeof","catch","for",
"private","foreach","protected","checked","goto","public",
"unchecked","class","if","readonly","unsafe","const","implicit","ref",
"continue","in","return","using","virtual","default",
"interface","sealed","volatile","delegate","internal","do","is",
"sizeof","while","lock","stackalloc","else","static","enum",
"namespace",
"object","bool","byte","float","uint","char","ulong","ushort",
"decimal","int","sbyte","short","double","long","string","void",
"partial", "yield", "where"
};
static void FillKeywordTable ()
{
lock (keywords) {
if (keywordsTable == null) {
keywordsTable = new Hashtable ();
foreach (string keyword in keywords) {
keywordsTable.Add (keyword, keyword);
}
}
}
}
static bool is_identifier_start_character (char c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c == '@' || Char.IsLetter (c);
}
static bool is_identifier_part_character (char c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9') || Char.IsLetter (c);
}
protectedoverride bool IsValidIdentifier(字符串标识符)
{
if(标识符==null | |标识符.长度==0)
返回false;
if(关键字稳定==null)
FillKeywordTable();
if(关键字stable.Contains(标识符))
返回false;
如果(!是\u标识符\u开始\u字符(标识符[0]))
返回false;
for(int i=1;i='a'&&c='a'&&c='a'&&c='a'&&c='0'&&c='a'&&c='a'&&c='a'&&c='a'&&c='0'&&c由于是开源的,代码分析工具唾手可得,而且它们是为性能而编写的。(现在它们已经在预发布中)
然而,我不能谈论加载程序集的性能成本
使用nuget安装工具:
Install-Package Microsoft.CodeAnalysis -Pre
问你的问题:
var isValid = Microsoft.CodeAnalysis.CSharp.SyntaxFacts.IsValidIdentifier("I'mNotValid");
Console.WriteLine(isValid); // False
现在发布的项目提供了与Java类似的Microsoft.CodeAnalysis.CSharp.SyntaxFacts
,以及SyntaxFacts.IsIdentifierStartCharacter(char)
和SyntaxFacts.IsIdentifierPartCharacter(char)
方法
在这里,它正在使用,在一个简单的函数中,我使用它将名词短语(例如“开始日期”)转换为C#标识符(例如“开始日期”)。注意:我使用它进行大小写转换,并使用Roslyn检查字符是否有效
public static string Identifier(string name)
{
Check.IsNotNullOrWhitespace(name, nameof(name));
// trim off leading and trailing whitespace
name = name.Trim();
// should deal with spaces => camel casing;
name = name.Dehumanize();
var sb = new StringBuilder();
if (!SyntaxFacts.IsIdentifierStartCharacter(name[0]))
{
// the first characters
sb.Append("_");
}
foreach(var ch in name)
{
if (SyntaxFacts.IsIdentifierPartCharacter(ch))
{
sb.Append(ch);
}
}
var result = sb.ToString();
if (SyntaxFacts.GetKeywordKind(result) != SyntaxKind.None)
{
result = @"@" + result;
}
return result;
}
测试
[TestCase("Start Date", "StartDate")]
[TestCase("Bad*chars", "BadChars")]
[TestCase(" leading ws", "LeadingWs")]
[TestCase("trailing ws ", "TrailingWs")]
[TestCase("class", "Class")]
[TestCase("int", "Int")]
[Test]
public void CSharp_GeneratesDecentIdentifiers(string input, string expected)
{
Assert.AreEqual(expected, CSharp.Identifier(input));
}
这确实有一些性能影响,你应该知道。请参阅我的帖子了解更多信息。OMG 7 upvows,它甚至不工作,甚至在我修复代码之前都没有编译…在它脱机之前已经存档。这是一个有用的事实,但没有帮助,因为你没有解释如何使用它。我似乎找不到一个“Microsoft.CodeAnalysis"NuGet软件包,我似乎也找不到解释在哪里可以获得该库的官方页面。我在第一个设置中提供了链接:。它说明:NuGet安装Microsoft.CodeAnalysis#安装语言API和服务
你应该安装Microsoft.CodeAnalysis.CSharp
,以获得C规则。它可能是同时检查“上下文关键字”是个好主意。您可以使用SyntaxFacts.GetKeywordKind(关键字)==SyntaxKind.None&&SyntaxFacts.getContextalKeyWordKind(关键字)==SyntaxKind.None
检查字符串是否为保留关键字或上下文关键字,或者使用SyntaxFacts.GetKeywordKinds()获取完整列表。选择(SyntaxFacts.GetText)