繁体   English   中英

“T”类型的值无法转换为

[英]Value of type 'T' cannot be converted to

这很可能是一个新手问题,但 google 出人意料地没有提供答案。

我有这个相当人为的方法

T HowToCast<T>(T t)
{
    if (typeof(T) == typeof(string))
    {
        T newT1 = "some text";
        T newT2 = (string)t;
    }

    return t;
}

来自 C++ 背景,我希望这能奏效。 但是,对于上述两个分配,它无法使用“无法将类型 'T' 隐式转换为字符串”和“无法将类型 'T' 转换为字符串”进行编译。

我要么在概念上做错了,要么只是语法错误。 请帮我解决这个问题。

谢谢!

即使它在if块内,编译器也不知道Tstring
因此,它不允许您进行投射。 (出于同样的原因,您不能将DateTimestring

您需要转换为object ,(任何T都可以转换为),然后从那里转换为string (因为object可以转换为string )。
例如:

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

两条线都有同样的问题

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

编译器不知道 T 是一个字符串,因此无法知道如何分配它。 但是既然你检查过了,你就可以用

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

您不需要强制转换 t 因为它已经是一个字符串,还需要添加约束

where T : class

我知道 OP 在这个问题中从通用解析器发布的类似代码。 从性能角度来看,您应该使用Unsafe.As<TFrom, TResult>(ref TFrom source) ,它可以在System.Runtime.CompilerServices.Unsafe NuGet 包中找到。 它避免了在这些场景中对值类型进行装箱。 我还认为Unsafe.As导致 JIT 生成的机器代码少于两次转换(使用(TResult) (object) actualString ),但我还没有检查出来。

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将被具有高效机器代码指令的 JIT 取代,正如您在官方 CoreFX 存储库中所见:

Unsafe.As 的源代码

如果您要检查显式类型,为什么要将这些变量声明为T

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;
}

如果您的类和方法都有通用声明,您也会收到此错误。 例如,下面显示的代码给出了这个编译错误。

public class Foo <T> {

    T var;

    public <T> void doSomething(Class <T> cls) throws InstantiationException, IllegalAccessException {
        this.var = cls.newInstance();
    }

}

这段代码确实可以编译(注意从方法声明中删除了 T):

public class Foo <T> {

    T var;

    public void doSomething(Class <T> cls) throws InstantiationException, IllegalAccessException {
        this.var = cls.newInstance();
    }

}

改变这一行:

if (typeof(T) == typeof(string))

对于这一行:

if (t.GetType() == typeof(string))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM