簡體   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