Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Value of type 'T' cannot be converted to

Even though it's inside of an if block, the compiler doesn't know that T is string.
Therefore, it doesn't let you cast. (For the same reason that you cannot cast DateTime to string)

You need to cast to object, (which any T can cast to), and from there to string (since object can be cast to string).
For example:

T newT1 = (T)(object)"some text";
string newT2 = (string)(object)t;

Both lines have the same problem

T newT1 = "some text";
T newT2 = (string)t;

The compiler doesn't know that T is a string and so has no way of knowing how to assign that. But since you checked you can just force it with

T newT1 = "some text" as T;
T newT2 = t; 

you don't need to cast the t since it's already a string, also need to add the constraint

where T : class

I know similar code that the OP posted in this question from generic parsers. From a performance perspective, you should use Unsafe.As<TFrom, TResult>(ref TFrom source), which can be found in the System.Runtime.CompilerServices.Unsafe NuGet package. It avoids boxing for value types in these scenarios. I also think that Unsafe.As results in less machine code produced by the JIT than casting twice (using (TResult) (object) actualString), but I haven't checked that out.

public TResult ParseSomething<TResult>(ParseContext context)
{
    if (typeof(TResult) == typeof(string))
    {
        var token = context.ParseNextToken();
        string parsedString = token.ParseToDotnetString();
        return Unsafe.As<string, TResult>(ref parsedString);
    }
    else if (typeof(TResult) == typeof(int))
    {
        var token = context.ParseNextToken();
        int parsedInt32 = token.ParseToDotnetInt32();
        // This will not box which might be critical to performance
        return Unsafe.As<int, TResult>(ref parsedInt32); 
    }
    // other cases omitted for brevity's sake
}

Unsafe.As will be replaced by the JIT with efficient machine code instructions, as you can see in the official CoreFX repo:

Source Code of Unsafe.As


If you're checking for explicit types, why are you declaring those variables as T's?

T HowToCast<T>(T t)
{
    if (typeof(T) == typeof(string))
    {
        var newT1 = "some text";
        var newT2 = t;  //this builds but I'm not sure what it does under the hood.
        var newT3 = t.ToString();  //for sure the string you want.
    }

    return t;
}