简体   繁体   English

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

[英]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块内,编译器也不知道Tstring
Therefore, it doesn't let you cast.因此,它不允许您进行投射。 (For the same reason that you cannot cast DateTime to string ) (出于同样的原因,您不能将DateTimestring

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 存储库中所见:

Unsafe.As 的源代码

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.

相关问题 无效对象无法转换为值类型 - Null object cannot be converted to a value type TypeLoadExceptionHolder无法转换为类型 - TypeLoadExceptionHolder cannot be converted to type 类型“ double”的值不能转换为“ System.Windows.Forms.DataGridViewCell” - Value of type 'double' cannot be converted to 'System.Windows.Forms.DataGridViewCell LINQ to SQL错误。 -类型无法转换为可为空的值 - LINQ to SQL Error. - The type can't be converted to nullable value &#39;CompareEndTodayValidator&#39;无法转换为&#39;Date&#39;类型。 - 'CompareEndTodayValidator' cannot be converted to type 'Date'.? 在LINQ dat source / gridview中使用文本框值作为参数:“String”类型的值无法转换为“Double”类型 - Using textbox value as parameter in LINQ dat source/gridview : A value of type 'String' cannot be converted to type 'Double' 数据源中String类型的给定值无法转换为指定目标列的float类型 - The given value of type String from the data source cannot be converted to type float of the specified target column 来自数据源的 String 类型的给定值无法转换为指定目标列的 nvarchar 类型 - The given value of type String from the data source cannot be converted to type nvarchar of the specified target column SQlBulkCopy 无法将数据源中 DateTime 类型的给定值转换为指定目标列的 int 类型 - SQlBulkCopy The given value of type DateTime from the data source cannot be converted to type int of the specified target column 常量值不能转换为int - Constant value cannot be converted to int
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM