快速解析字符串到运行时提供的其他类型?

时间:2014-09-04 19:38:11

标签: c#

我正在尝试构建更快版本的Convert.ChangeType。该类型在运行时提供。该函数用于解析文本文件等字符串。

public static object ConvertTo(Type t, string s)
{
    if (string.IsNullOrWhiteSpace(s) || s == null || Convert.IsDBNull(s)) return null;
    if (t == typeof(string)) return s; 
    if (t == typeof(DateTime)) { .... /* parse and return it */ }
    if (t == typeof(int)) { return int.Parse(s); }
    ....
    return Convert.ChangeType(s, t, CultureInfo.InvariantCulture); // Slowest
}

但是,它在分析中仍然是最慢的部分。这是一种提高速度的方法吗?

1 个答案:

答案 0 :(得分:1)

将字符串转换为另一种类型本身就很昂贵。但是,Convert.ChangeType正在进行虚拟接口调用和装箱/拆箱,你可以避免。

这是它在幕后做的事情:

public static object ChangeType(object value, Type conversionType, IFormatProvider provider)
{
  if (conversionType == (Type) null)
    throw new ArgumentNullException("conversionType");
  if (value == null)
  {
    if (conversionType.IsValueType)
      throw new InvalidCastException(Environment.GetResourceString("InvalidCast_CannotCastNullToValueType"));
    else
      return (object) null;
  }
  else
  {
    IConvertible convertible = value as IConvertible;
    if (convertible == null)
    {
      if (value.GetType() == conversionType)
        return value;
      else
        throw new InvalidCastException(Environment.GetResourceString("InvalidCast_IConvertible"));
    }
    else
    {
      RuntimeType runtimeType = conversionType as RuntimeType;
      if (runtimeType == Convert.ConvertTypes[3])
        return (object) (bool) (convertible.ToBoolean(provider) ? 1 : 0);
      if (runtimeType == Convert.ConvertTypes[4])
        return (object) convertible.ToChar(provider);
      if (runtimeType == Convert.ConvertTypes[5])
        return (object) convertible.ToSByte(provider);
      if (runtimeType == Convert.ConvertTypes[6])
        return (object) convertible.ToByte(provider);
      if (runtimeType == Convert.ConvertTypes[7])
        return (object) convertible.ToInt16(provider);
      if (runtimeType == Convert.ConvertTypes[8])
        return (object) convertible.ToUInt16(provider);
      if (runtimeType == Convert.ConvertTypes[9])
        return (object) convertible.ToInt32(provider);
      if (runtimeType == Convert.ConvertTypes[10])
        return (object) convertible.ToUInt32(provider);
      if (runtimeType == Convert.ConvertTypes[11])
        return (object) convertible.ToInt64(provider);
      if (runtimeType == Convert.ConvertTypes[12])
        return (object) convertible.ToUInt64(provider);
      if (runtimeType == Convert.ConvertTypes[13])
        return (object) convertible.ToSingle(provider);
      if (runtimeType == Convert.ConvertTypes[14])
        return (object) convertible.ToDouble(provider);
      if (runtimeType == Convert.ConvertTypes[15])
        return (object) convertible.ToDecimal(provider);
      if (runtimeType == Convert.ConvertTypes[16])
        return (object) convertible.ToDateTime(provider);
      if (runtimeType == Convert.ConvertTypes[18])
        return (object) convertible.ToString(provider);
      if (runtimeType == Convert.ConvertTypes[1])
        return value;
      else
        return convertible.ToType(conversionType, provider);
    }
  }
}

这是它使用的类型数组:

internal static readonly RuntimeType[] ConvertTypes = new RuntimeType[19]
{
  (RuntimeType) typeof (Empty),
  (RuntimeType) typeof (object),
  (RuntimeType) typeof (DBNull),
  (RuntimeType) typeof (bool),
  (RuntimeType) typeof (char),
  (RuntimeType) typeof (sbyte),
  (RuntimeType) typeof (byte),
  (RuntimeType) typeof (short),
  (RuntimeType) typeof (ushort),
  (RuntimeType) typeof (int),
  (RuntimeType) typeof (uint),
  (RuntimeType) typeof (long),
  (RuntimeType) typeof (ulong),
  (RuntimeType) typeof (float),
  (RuntimeType) typeof (double),
  (RuntimeType) typeof (Decimal),
  (RuntimeType) typeof (DateTime),
  (RuntimeType) typeof (object),
  (RuntimeType) typeof (string)
};