Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Faster version of Convert.ChangeType

Tags:

c#

In an application that I have, I am doing quite frequent calls to Convert.ChangeType in order to convert a value to a dynamically loaded type.

However, after profiling with ANTS, I've found that this Convert.ChangeType seems to take a significant portion of time (due to being called quite often). Does anyone have a faster alternative to doing this?

At this point I have a type object containing the target, and a string containing the value.

The following is the offending code. I was considering doing a switch-statement on type (since it is a limited collection of types) and calling the parse methods, though I'm not sure whether or not that'll be faster.

if(attributeRow["Value"]!=DBNull.Value)
    sample[attr] = attr.AttributeType == typeof(Guid)
                 ? new Guid(attributeRow["Value"].ToString())
                 : (IComparable)Convert.ChangeType(attributeRow["Value"],attr.AttributeType);
like image 541
Erich Avatar asked Oct 07 '09 15:10

Erich


3 Answers

I'm not aware of any other functionality within the framework itself for changing Types other than the Convert.ChangeType function (and explicit casts, obviously).

For this, I think the only other way to improve this is to roll your own ChangeType function that is specifically optimized for your particular situation (if possible).

You mention that you're working with a limited number of Types, perhaps you're dealing with one Type more than the others? Is so, your ChangeType function could be optimized to attempt this specific conversion first, and only trying others if failing. You mention trying a switch-style block of code, and this same approach (trying the most frequently used Type first) could be applied to that. As to whether it will be faster would depend upon your data that you're processing (and the frequency/variability of the Types you're converting to/from) and the only real way to measure this is to try it and profile it in comparison with the Convert.ChangeType methodology.

One interesting link if you're looking to roll-your-own functionality is on Peter Johnson's blog:

Convert.ChangeType doesn't handle nullables

Be sure to read all of the comments to the post also.

like image 74
CraigTP Avatar answered Nov 14 '22 14:11

CraigTP


This is my version of a faster ChangeType. I guess the principle is the same as suggested by @CraigTP, however, it will only work for nullable value types.

I'm basing my convert method on the fact that it's more likely that the type of value will be compatible with the target type is some way. But this method wasn't designed for performance it was designed to be convenient. It's not something I'd wanna invoke from within a tight loop.

I'm still falling back on ChangeType but I try to opt out as early as possible.

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?);
}
like image 3
John Leidegren Avatar answered Nov 14 '22 14:11

John Leidegren


I haven't tested if faster, but this is an alternative way for dynamic casting. This is alsp more universal, since Convert.ChangeType() has some limitations, as you have seen (Guids, Nullable types)

value = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(str);
like image 2
d.popov Avatar answered Nov 14 '22 12:11

d.popov