views:

1596

answers:

5

Hello guys, 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());
    }

}
A: 

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.

Andrew Hare
I understand. But why I can't convert it when it is a uint? Do you think its necessary to put a 'u' at the end of the assigment? like:object o = 10u;as Jon has proposed?Cheers
Andres
You would have to because that gives a hint to the compiler to infer a ulong rather than an int.
Andrew Hare
+2  A: 

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));
Adam Robinson
+7  A: 

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.

Jon Skeet
A: 

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! :)

JP Alioto
A: 

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.

Chris Shaffer