2014-09-04 49 views
2

我试图构建一个更快的版本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 
} 

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

+4

尝试使用一些键集合来存储转换的功能,如'词典<类型,类似'HashTable'的Func >。 – 2014-09-04 19:41:12

+11

这就是为什么你应该首先避免这种情况。开始时,这是一个固有的昂贵的问题,将某些东西转换为编译时未知的类型。你应该很少会遇到这种情况。在大多数情况下,你应该在编译时知道你想要的类型。另外请记住,如果只有一些银弹来解决这个问题,你不认为这将被用作'Convert.ChangeType'的定义吗? – Servy 2014-09-04 19:42:36

+2

@EugenePodskal只有少数几种类型不可能产生有意义的区别。他必须有几十种甚至数百种类型才能开始重要。 – Servy 2014-09-04 19:43:10

回答

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