无法将类型'Int'隐式转换为'T'

Dav*_*d W 77 c# generics

我可以打电话Get<int>(Stat);Get<string>(Name);

但是在编译时,我得到:

无法将类型'int'隐式转换为'T'

同样的事情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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Bro*_*ass 125

您应该只能使用Convert.ChangeType()而不是自定义代码:

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

  • 如何`return(T)(object)PlayerStats [type];` (14认同)
  • 比“你不应该”好得多 (3认同)

Eri*_*ert 122

每当你发现自己打开通用类型时,你几乎肯定会做错事.泛型应该是通用的 ; 它们应该完全独立于类型操作.

如果T只能是int或string,那么首先不要以这种方式编写代码.编写两个方法,一个返回一个int,另一个返回一个字符串.

  • 我只能部分同意你,@ Eric.我有一种情况,我必须解析存储在XML标签中的数组.问题是XML文档遵循的规范(在我的情况下是COLLADA)说这样的数组可以是不仅有float,int和bool,还有一些自定义类型.但是如果你得到一个float [](array-tags包含其名称中存储数据的类型:float_array存储浮点数),你需要将字符串解析为一个数组浮点数,需要使用一些IFormatProvider).我显然不能使用"T.Parse(...)".所以对于一小部分情况我需要使用这种切换. (7认同)
  • 你能详细说明这会出错吗? (4认同)
  • 这个答案将使您远离兔子洞。我想为“int, int?, bool, bool?, string”创建一个通用函数,这似乎是不可能的。 (2认同)

Rez*_*eni 11

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `return(T)t;`因为不需要空检查. (2认同)

小智 8

ChangeType可能是你最好的选择.我的解决方案类似于BrokenGlass提供的一个try catch逻辑.

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;
}
Run Code Online (Sandbox Code Playgroud)


Pra*_*thi 7

考虑到 @BrokenGlass 逻辑 ( Convert.ChangeType) 不支持 GUID 类型。

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

错误:从“System.String”到“System.Guid”的无效转换。

相反,TypeDescriptor.GetConverter通过添加System.ComponentModel命名空间使用以下逻辑。

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

这个


小智 6

试试这个:

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];
    }
}
Run Code Online (Sandbox Code Playgroud)


Gre*_*rko 6

实际上,您可以将其转换为object,然后转换为T

T var = (T)(object)42;

的示例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
    }
}
Run Code Online (Sandbox Code Playgroud)

有时,这种行为是可取的。例如,当从基类或接口实现或重写泛型方法时,您要基于T类型添加一些不同的功能。