8

I'm writing a method to do a intelligent type conversion - using ToString() if the type parameter happens to be a string, otherwise casting but returning null if the cast doesn't work. Basically gets as much information out of v it can without throwing an exception.

I check that T is indeed a string before I attempt the cast, but the compiler is still not a fan:

Cannot convert type 'string' to 'T'

And here's my method:

public T? Convert<T>(object v)
{
    if (typeof(T) == typeof(string)) {
    return (T)v.ToString(); // Cannot convert type 'string' to 'T'  
    } else try {
      return (T)v;
    } catch (InvalidCastException) {
    return null;
    }
}

Also let me know if this is some sort of unforgivable sin. I'm using it to deal with some data structures that could have mixed types.

1
  • There are other problems. Your method cannot have return type T? when there's no constraint on T. For example there's nothing called string? because string is a reference type. Commented Aug 8, 2012 at 15:05

4 Answers 4

31

You basically need to go via object when casting to a generic type:

return (T)(object) v.ToString()

and

return (T)(object) v;

I would use is rather than catching an InvalidCastException though.

See Eric Lippert's recent blog post for more details of why this is necessary.

In particular:

Because the compiler knows that the only way this conversion could possibly succeed is if U is bool, but U can be anything! The compiler assumes that most of the time U is not going to be constructed with bool, and therefore this code is almost certainly an error, and the compiler is bringing that fact to your attention.

(Substitute T for U and string for bool...)

Sign up to request clarification or add additional context in comments.

5 Comments

Wouldn't as be the better choice here?
@SteveCzetty: We don't know that T is a nullable type, so as wouldn't work (IIRC).
Good point. Though I don't think is will work either, unless T is constrained to a class. (IIRC, also)
@SteveCzetty: Yes it will - you can use is with any kind of type. For example: object o = 10; if (o is int) ...
@BehnamEsmaili: where is the value type that would be boxed?
3

You need to cast your string as object as your return type is generic i.e.

return (T)(object)v.ToString();

1 Comment

That's not boxing. There are no value types involved.
0

Try to convert to object before converting to T

return (T)(object)v; 

Comments

0
using System.ComponentModel;

...

public T Convert<T>(object v) {
    return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(v);
}

Warning, this will throw an exception if no conversion exists between T and the object contained in v.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.