在我拥有的应用程序中,我经常调用Convert.ChangeType
来将值转换为动态加载类型。
然而,在使用ANTS进行分析之后,我发现这个Convert.ChangeType
似乎占用了相当长的一部分时间(由于经常被调用)。有没有人有更快的替代方法呢?
此时我有一个包含目标的类型对象,以及一个包含该值的string
。
以下是违规代码。我正在考虑在类型上做一个switch语句(因为它是一个有限的类型集合)并调用解析方法,虽然我不确定它是否会更快。
if(attributeRow["Value"]!=DBNull.Value)
sample[attr] = attr.AttributeType == typeof(Guid)
? new Guid(attributeRow["Value"].ToString())
: (IComparable)Convert.ChangeType(attributeRow["Value"],attr.AttributeType);
答案 0 :(得分:9)
我不知道框架内部有任何其他功能可以更改Convert.ChangeType
函数以外的类型(显然是显式转换)。
为此,我认为唯一可以改进的方法是推出自己的ChangeType
函数,该函数专门针对您的特定情况进行了优化(如果可能)。
你提到你正在使用有限数量的类型,也许你比其他类型更多地处理一种类型?是这样,您的ChangeType
功能可以优化以首先尝试此特定转换,并且只有在失败时才尝试其他转换。您提到尝试切换样式的代码块,并且可以将相同的方法(尝试最常用的Type)应用于此。至于它是否会更快将取决于您正在处理的数据(以及您要转换/转换的类型的频率/可变性),唯一真正的衡量方法是尝试并将其分析到与Convert.ChangeType
方法进行比较。
如果您正在寻找自己的功能,那么一个有趣的链接就在Peter Johnson的博客上:
Convert.ChangeType doesn't handle nullables
请务必阅读该帖子的所有评论。
答案 1 :(得分:3)
这是我更快的ChangeType版本。我猜这个原理与@CraigTP建议的原理相同,但是它只适用于可以为空的值类型。
我的转换方法基于以下事实:值的类型更可能与目标类型兼容。但是这种方法并不是为了方便而设计的。这不是我想要在紧密循环中调用的东西。
我仍在使用ChangeType,但我尽量选择退出。
public static T? ToOrDefault<T>(object value)
where T : struct, IConvertible
{
var x = value as T?;
if (x.HasValue)
{
return x;
}
if (value == null || Convert.IsDBNull(value))
{
return null;
}
try
{
return (T)Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture);
}
catch (InvalidCastException)
{
}
catch (FormatException)
{
}
catch (OverflowException)
{
}
catch (ArgumentException)
{
}
return default(T?);
}
答案 2 :(得分:1)
我没有测试过更快,但这是动态投射的另一种方式。这是更普遍的,因为Convert.ChangeType()
有一些限制,如你所见(Guids,Nullable类型)
value = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(str);
答案 3 :(得分:0)
您可以滚动自己的ChangeType
函数,该函数只执行静态C风格的转换。那将是我的方法。
答案 4 :(得分:-1)
我知道这听起来很疯狂,但是,您可以使用Newtonsoft JSON.NET将您的对象转换为序列化的字符串,然后将该字符串转换为任何其他类型。
def to_bool(x)
!!x
end
to_bool(1) #=> true
to_bool(0) #=> true
to_bool("0") #=> true
to_bool("1") #=> true
to_bool(Object.new) #=> true
to_bool(nil) #=> false