Cannot implicitly convert type 'Int' to 'T'

C#Generics

C# Problem Overview


I can call Get<int>(Stat); or Get<string>(Name);

But when compiling I get:

> Cannot implicitly convert type 'int' to 'T'

and the same thing for string.

public T Get<T>(Stats type) where T : IConvertible
{
    if (typeof(T) == typeof(int))
    {
        int t = Convert.ToInt16(PlayerStats[type]);
        return t;
    }
    if (typeof(T) == typeof(string))
    {
        string t = PlayerStats[type].ToString();
        return t;
    }
}

C# Solutions


Solution 1 - C#

You should be able to just use Convert.ChangeType() instead of your custom code:

public T Get<T>(Stats type) where T : IConvertible
{
    return (T) Convert.ChangeType(PlayerStats[type], typeof(T));
}

Solution 2 - C#

Any time you find yourself switching on a type in a generic you are almost certainly doing something wrong. Generics should be generic; they should operate identically completely independent of the type.

If T can only be int or string then don't write your code this way at all in the first place. Write two methods, one that returns an int and one that returns a string.

Solution 3 - C#

Actually, you can just convert it to object and then to T.

T var = (T)(object)42;

An example for bool:

public class Program
{
    public static T Foo<T>()
    {
	    if(typeof(T) == typeof(bool)) {
		    return (T)(object)true;
	    }
	    
	    return default(T);
    }
    
    public static void Main()
    {
	    bool boolValue = Foo<bool>(); // == true
	    string stringValue = Foo<string>(); // == null
    }
}

Sometimes, this behavior is desirable. For instance, when implementing or overriding a generic method from a base class or interface and you want to add some different functionalities based on the T type.

Solution 4 - C#

public T Get<T>(Stats type ) where T : IConvertible
{
    if (typeof(T) == typeof(int))
    {
        int t = Convert.ToInt16(PlayerStats[type]);
        return (T)t;
    }
    if (typeof(T) == typeof(string))
    {
        string t = PlayerStats[type].ToString();
        return (T)t;
    }
}

Solution 5 - C#

ChangeType is probably your best option. My solution is similar to the one provided by BrokenGlass with a bit of try catch logic.

static void Main(string[] args)
{
    object number = "1";
    bool hasConverted;
    var convertedValue = DoConvert<int>(number, out hasConverted);

    Console.WriteLine(hasConverted);
    Console.WriteLine(convertedValue);
}

public static TConvertType DoConvert<TConvertType>(object convertValue, out bool hasConverted)
{
    hasConverted = false;
    var converted = default(TConvertType);
    try
    {
        converted = (TConvertType) 
            Convert.ChangeType(convertValue, typeof(TConvertType));
        hasConverted = true;
    }
    catch (InvalidCastException)
    {
    }
    catch (ArgumentNullException)
    {
    }
    catch (FormatException)
    {
    }
    catch (OverflowException)
    {
    }

    return converted;
}

Solution 6 - C#

Try this:

public T Get<T>(Stats type ) where T : IConvertible
{
    if (typeof(T) == typeof(int))
    {
        return (T)(object)Convert.ToInt16(PlayerStats[type]);
    
    }
    if (typeof(T) == typeof(string))
    {
    
        return (T)(object)PlayerStats[type];
    }
}

Solution 7 - C#

Considering @BrokenGlass logic (Convert.ChangeType) does not support for GUID type.

public T Get<T>(Stats type) where T : IConvertible
{
    return (T) Convert.ChangeType(PlayerStats[type], typeof(T));
}

Error: Invalid cast from 'System.String' to 'System.Guid'.

Instead, use below logic using TypeDescriptor.GetConverter by adding System.ComponentModel namespace.

public T Get<T>(Stats type) where T : IConvertible
{
    (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(PlayerStats[type])
}

Read this.

Solution 8 - C#

It looks like you need a TypeConverter, see this blog entry.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDavid WView Question on Stackoverflow
Solution 1 - C#BrokenGlassView Answer on Stackoverflow
Solution 2 - C#Eric LippertView Answer on Stackoverflow
Solution 3 - C#GregorMohorkoView Answer on Stackoverflow
Solution 4 - C#Reza ArabQaeniView Answer on Stackoverflow
Solution 5 - C#Michael CibaView Answer on Stackoverflow
Solution 6 - C#Michael KalinovichView Answer on Stackoverflow
Solution 7 - C#Prasad KanaparthiView Answer on Stackoverflow
Solution 8 - C#Ian MercerView Answer on Stackoverflow