[英]Value of type 'T' cannot be converted to
This is likely aa novice question, but google surprisingly did not provide an answer.这很可能是一个新手问题,但 google 出人意料地没有提供答案。
I have this rather artificial method我有这个相当人为的方法
T HowToCast<T>(T t)
{
if (typeof(T) == typeof(string))
{
T newT1 = "some text";
T newT2 = (string)t;
}
return t;
}
Coming from a C++ background I have expected this to work.来自 C++ 背景,我希望这能奏效。 However, it fails to compile with "Cannot implicitly convert type 'T' to string" and "Cannot convert type 'T' to string" for both of the above assignments.
但是,对于上述两个分配,它无法使用“无法将类型 'T' 隐式转换为字符串”和“无法将类型 'T' 转换为字符串”进行编译。
I am either doing something conceptually wrong or just have the wrong syntax.我要么在概念上做错了,要么只是语法错误。 Please help me sort this one out.
请帮我解决这个问题。
Thank you!谢谢!
Even though it's inside of an if
block, the compiler doesn't know that T
is string
.即使它在
if
块内,编译器也不知道T
是string
。
Therefore, it doesn't let you cast.因此,它不允许您进行投射。 (For the same reason that you cannot cast
DateTime
to string
) (出于同样的原因,您不能将
DateTime
为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
).您需要转换为
object
,(任何T
都可以转换为),然后从那里转换为string
(因为object
可以转换为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.编译器不知道 T 是一个字符串,因此无法知道如何分配它。 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您不需要强制转换 t 因为它已经是一个字符串,还需要添加约束
where T : class
I know similar code that the OP posted in this question from generic parsers.我知道 OP 在这个问题中从通用解析器发布的类似代码。 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.从性能角度来看,您应该使用
Unsafe.As<TFrom, TResult>(ref TFrom source)
,它可以在System.Runtime.CompilerServices.Unsafe NuGet 包中找到。 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.我还认为
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
will be replaced by the JIT with efficient machine code instructions, as you can see in the official CoreFX repo: Unsafe.As
将被具有高效机器代码指令的 JIT 取代,正如您在官方 CoreFX 存储库中所见:
If you're checking for explicit types, why are you declaring those variables as T
's?如果您要检查显式类型,为什么要将这些变量声明为
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;
}
You will also get this error if you have a generic declaration for both your class and your method.如果您的类和方法都有通用声明,您也会收到此错误。 For example the code shown below gives this compile error.
例如,下面显示的代码给出了这个编译错误。
public class Foo <T> {
T var;
public <T> void doSomething(Class <T> cls) throws InstantiationException, IllegalAccessException {
this.var = cls.newInstance();
}
}
This code does compile (note T removed from method declaration):这段代码确实可以编译(注意从方法声明中删除了 T):
public class Foo <T> {
T var;
public void doSomething(Class <T> cls) throws InstantiationException, IllegalAccessException {
this.var = cls.newInstance();
}
}
Change this line:改变这一行:
if (typeof(T) == typeof(string))
For this line:对于这一行:
if (t.GetType() == typeof(string))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.