问题描述
整数文字的类型由其后缀确定,如下所示:
如果字面量没有后缀,则其类型是以下类型中第一个可以表示其值的类型:int、uint、long、ulong。
如果文字以 U 或 u 为后缀,则其类型是以下类型中可以表示其值的第一个类型:uint、ulong。
如果文字以 L 或 l 为后缀,则其类型是以下类型中第一个可以表示其值的类型:long、ulong。
如果文字后缀为 UL、Ul、uL、ul、LU、Lu、lU 或 lu,则其类型为 ulong。
.Net 标准库包含多个函数,用于使用各种选项将字符串解析为整数。
是否有任何这样的函数可以应用上述逻辑,甚至是其中的一部分,根据后缀、大小或两者返回几种整数类型之一?
解决方法
一个函数只能有一个返回类型,而且由于不同的整数类型实际上是不同的 dotnet 数据类型,因此不可能存在一个可以返回其中任何一个的单一方法......除非你变得聪明并返回一个组合目的!类似的东西:
public class CleverReturn
{
public Object ParsedReturnValue { get; set; }
public string ParsedReturnValueType { get; set; }
}
'ParsedReturnValueType' 将包含类型的完整命名空间和类型名称。您可以使用它通过反射创建正确类型的变量,并将 ParsedReturnValue 转换为它。但我知道 .NET API 中没有这样的方法。
,至于您的问题(是否有解析 C# 整数文字的标准函数)- 答案是否定的。
我不确定他们将如何返回将被解析的值。我使用了一个相当长的元组:
(bool succeeded,Type theType,int i,uint iU,long iL,ulong iUL)
通过这种方式,您可以获得解析是否成功的指示(à la int.TryParse
),以及解析成功的类型的指示,以及获取值的方法(无论是什么类型)。>
在那之后,我只是蛮力,使用正则表达式来解析输入字符串的部分。顺便说一下,我很确定 -234
和 +678
都是有效的整数文字;所以我也照顾好这个标志。
我从 Regex 模式和 Regex 开始:
private const string literalPattern = @"(?<prefix>[+-]?)(?<number>[0-9]+)(?<suffix>(ul|lu|u|l)?)";
private static Regex literalRegex = new Regex(literalPattern,RegexOptions.IgnoreCase);
(?<name>pattern)
模式允许命名组。您可以看到我在以下表达式中使用它们:match.Groups["prefix"].ToString()
。
然后我有我的蛮力解析代码:
public static (bool,Type,int,uint,long,ulong) ParseIntegerLiteral(string theLiteral)
{
(bool,ulong) badReturn = (false,null,0);
var match = literalRegex.Match(theLiteral);
if (match.Groups.Count == 0)
{
return badReturn;
}
var negativeMult = 1;
if (string.Equals(match.Groups["prefix"].ToString(),"-",StringComparison.OrdinalIgnoreCase))
{
negativeMult = -1;
}
Type type;
var i = 0;
var iu = 0U;
var il = 0L;
var iul = 0UL;
switch (match.Groups["suffix"].ToString().ToUpper())
{
case "L":
type = typeof(long);
if (!long.TryParse(match.Groups["number"].ToString(),out il))
{
return badReturn;
}
break;
case "U":
type = typeof(uint);
if (negativeMult == -1)
{
return badReturn;
}
if (!uint.TryParse(match.Groups["number"].ToString(),out iu))
{
return badReturn;
}
iul = iu;
break;
case "UL":
case "LU":
type = typeof(ulong);
if (negativeMult == -1)
{
return badReturn;
}
if (!ulong.TryParse(match.Groups["number"].ToString(),out iul))
{
return badReturn;
}
break;
default:
type = typeof(int);
if (!int.TryParse(match.Groups["number"].ToString(),out i))
{
return badReturn;
}
i *= negativeMult;
il = i;
if (i >= 0)
{
iu = (uint)i;
iul = (ulong)i;
}
break;
}
return (true,type,i,iu,il,iul);
}
与往常一样,代码经过了非常轻松的测试。您需要为它编写一些单元测试。