将字符串转换为另一种类型本身就很昂贵。但是,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)
};
尝试使用一些键集合来存储转换的功能,如'词典<类型,类似'HashTable'的Func
这就是为什么你应该首先避免这种情况。开始时,这是一个固有的昂贵的问题,将某些东西转换为编译时未知的类型。你应该很少会遇到这种情况。在大多数情况下,你应该在编译时知道你想要的类型。另外请记住,如果只有一些银弹来解决这个问题,你不认为这将被用作'Convert.ChangeType'的定义吗? – Servy 2014-09-04 19:42:36
@EugenePodskal只有少数几种类型不可能产生有意义的区别。他必须有几十种甚至数百种类型才能开始重要。 – Servy 2014-09-04 19:43:10