gpt4 book ai didi

c# - 检查字符串是否可以被解析的最快方法

转载 作者:IT王子 更新时间:2023-10-29 04:49:10 24 4
gpt4 key购买 nike

我正在将 CSV 文件解析为具有强类型属性的对象列表。这涉及将文件中的每个字符串值解析为 IConvertible 类型(intdecimaldoubleDateTime 等)使用 TypeDescriptor

我正在使用 try catch 来处理解析失败的情况。然后记录此异常发生的位置和原因的确切详细信息以供进一步调查。下面是实际解析代码:

try
{
parsedValue = TypeDescriptor.GetConverter(type).ConvertFromString(dataValue);
}
catch (Exception ex)
{
// Log failure
}

问题:

成功解析值后,过程很快。当解析包含大量无效数据的数据时,该过程可能会慢数千倍(由于捕获异常)。

我一直在通过解析到 DateTime 来测试它。这些是性能数据:

  • 成功解析:平均每次解析32 次
  • 解析失败:平均每次解析146296 次

慢了 4500 多倍。

问题:

我是否可以检查一个字符串值是否可以被成功解析,而不必使用我昂贵的 try catch 方法?或者我应该用另一种方法来做这件事?

编辑:我需要使用 TypeDescriptor(而不是 DateTime.TryParse),因为类型是在运行时确定的。

最佳答案

如果您有一组已知类型要转换,您可以在类型名称上执行一系列 if/elseif/elseif/else(或 switch/case ) 本质上将其分发给专门的解析方法。这应该很快。这如 @Fabio's answer 中所述.

如果您仍然遇到性能问题,您还可以创建一个查找表,让您可以根据需要添加新的解析方法来支持它们:

给定一些基本的解析包装器:

public delegate bool TryParseMethod<T>(string input, out T value);

public interface ITryParser
{
bool TryParse(string input, out object value);
}

public class TryParser<T> : ITryParser
{
private TryParseMethod<T> ParsingMethod;

public TryParser(TryParseMethod<T> parsingMethod)
{
this.ParsingMethod = parsingMethod;
}

public bool TryParse(string input, out object value)
{
T parsedOutput;
bool success = ParsingMethod(input, out parsedOutput);
value = parsedOutput;
return success;
}
}

然后您可以设置一个转换助手来执行查找并调用适当的解析器:

public static class DataConversion
{
private static Dictionary<Type, ITryParser> Parsers;

static DataConversion()
{
Parsers = new Dictionary<Type, ITryParser>();
AddParser<DateTime>(DateTime.TryParse);
AddParser<int>(Int32.TryParse);
AddParser<double>(Double.TryParse);
AddParser<decimal>(Decimal.TryParse);
AddParser<string>((string input, out string value) => {value = input; return true;});
}

public static void AddParser<T>(TryParseMethod<T> parseMethod)
{
Parsers.Add(typeof(T), new TryParser<T>(parseMethod));
}

public static bool Convert<T>(string input, out T value)
{
object parseResult;
bool success = Convert(typeof(T), input, out parseResult);
if (success)
value = (T)parseResult;
else
value = default(T);
return success;
}

public static bool Convert(Type type, string input, out object value)
{
ITryParser parser;
if (Parsers.TryGetValue(type, out parser))
return parser.TryParse(input, out value);
else
throw new NotSupportedException(String.Format("The specified type \"{0}\" is not supported.", type.FullName));
}
}

那么用法可能是这样的:

//for a known type at compile time
int value;
if (!DataConversion.Convert<int>("3", out value))
{
//log failure
}

//or for unknown type at compile time:
object value;
if (!DataConversion.Convert(myType, dataValue, out value))
{
//log failure
}

这可能会扩展泛型以避免 object 装箱和类型转换,但就目前而言,它工作正常;如果您从中获得可衡量的性能,也许只优化该方面。

编辑:您可以更新 DataConversion.Convert 方法,这样如果它没有注册指定的转换器,它可以回退到您的 TypeConverter 方法或抛出适当的异常。这取决于您是想要包罗万象还是只是拥有预定义的支持类型集并避免再次使用 try/catch。就目前而言,代码已更新为抛出 NotSupportedException 并显示一条消息,指示不受支持的类型。随意调整,因为它是有道理的。在性能方面,也许做全包是有意义的,因为一旦您为最常用的类型指定专门的解析器,这些包可能会越来越少。

关于c# - 检查字符串是否可以被解析的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16835750/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com