Question

I'm trying to write some code to convert data from a object type field (come from a DataSet) into it's destination (typed) fields. I'm doing (trying at least) it using dynamic conversion. It seems to work fine for strings, int, DateTime.

But it doesn't work for unsigned types (ulong, uint). Below there's a simple code that shows what I want to do. If you change the ul var type from ulong to int, it works fine.

Does anybody have a clue?

public class console
{

    public static void CastIt<T>(object value, out T target)
    {
        target = (T) value;
    }

    public static void Main()
    {
        ulong ul;
        string str;
        int i;
        DateTime dt;

        object ul_o = (object) 2;
        object str_o = (object) "This is a string";
        object i_o = (object)1;
        object dt_o = (object) DateTime.Now;

        Console.WriteLine("Cast");

        CastIt(ul_o, out ul);
        CastIt(str_o, out str);
        CastIt(i_o, out i);
        CastIt(dt_o, out dt);

        Console.WriteLine(ul);
        Console.WriteLine(str);
        Console.WriteLine(i);
        Console.WriteLine(dt.ToString());
    }

}
Was it helpful?

Solution

As Andrew says, the problem is that you can't unbox from a boxed int to ulong.

Two options:

1) Box a ulong instead:

object ul_o = (object) 2UL;

or

ulong tmp = 2;
object ul_o = tmp;

2) Make CastIt<T> use Convert.ChangeType:

public static void CastIt<T>(object value, out T target)
{
    target = (T) Convert.ChangeType(value, typeof(T));
}

This is a bit smelly, but works with your example code. If you can use the first way in your real code, that would be better.

OTHER TIPS

That's because your ul_o object is an int, not an unsigned number. When you're in your casting function, you're casting while having the target data in the context of an object. Explicit/implicit cast operators (which is what you'd need to be using) only work when you have the object in the context of a type that implements them (since those operators are statically linked at compile time rather than dynamically at runtime).

If this is really what you want to do, instead of just a straight cast, use this:

target = (T)Convert.ChangeType(value, typeof(T));

The CLR does not allow you to cast this way because your boxed value type is in fact an int:

object ul_o = (object)2;

When you are attempting to cast to a ulong you cannot because you cannot unbox an int directly into a ulong.

I think what you want is more like (untested, but directionally correct) ...

public static void CastIt<T>( object value ) where T : IConvertable
{
  return ( T )Convert.ChangeType( value , typeof( T ) );
}

Edit: Scooped by Skeet! :)

This is not really an answer to your question; Just wanted to mention that if you are using .Net 3.5, the Linq to DataSets code includes functionality like what you are implementing. The specific extension method would be Field<T>() on the DataRow class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top