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

时间:2010-11-03 22:55:56

标签: c# .net generics casting

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

我有这种相当人为的方法

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

    return t;
}

来自C ++背景我希望这可行。但是,无法编译“无法将类型'T'隐式转换为字符串”和“无法将类型'T'转换为字符串”以进行上述两种分配。

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

谢谢!

6 个答案:

答案 0 :(得分:253)

即使它在if块内,编译器也不知道Tstring
因此,它不会让你施展。 (出于同样的原因,你无法将DateTime强制转换为string

您需要转换为object,(任何T可以转换为),并从那里转换为string(因为object可以转换为{{1} }})。
例如:

string

答案 1 :(得分:9)

这两行都有同样的问题

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

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

来强迫它
T newT1 = "some text" as T;
T newT2 = t; 

你不需要施放t,因为它已经是一个字符串,还需要添加约束

where T : class

答案 2 :(得分:1)

如果您要检查显式类型,为什么要将这些变量声明为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;
}

答案 3 :(得分:0)

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

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

}

答案 4 :(得分:0)

我从通用解析器知道OP在此问题中发布的类似代码。从性能角度来看,您应该使用Sample code would be: ArrayList<Account> accounts; ArrayList<String> linesOfFile = readFile("file.txt"); int count = 0; for (String line : linesOfFile) { if (Character.isDigit(line.charAt(0)) count = Integer.parseInt(line); if (count != 0) { String[] accountDetails = line.split(" "); if (!accountExists(new Account (accountDetails[0], accountDetails[1]))) { accounts.add(new Account(accountDetails[0], accountDetails[1]); } count--; } // This is the part I want to add for the Transactions. } ,可以在System.Runtime.CompilerServices.Unsafe NuGet包中找到它。在这些情况下,它避免为值类型装箱。我还认为,<svg width="200" height="200"> <g transform="translate(200, 0) scale(-1, 1)"> <path stroke="green" strokeWidth="3" fill="none" d="M 0 0 L 100 100" /> </g> </svg>导致JIT产生的机器代码少于两次铸造(使用Unsafe.As<TFrom, TResult>(ref TFrom source)),但是我还没有检查出来。

Unsafe.As

(TResult) (object) actualString将由JIT替换为有效的机器代码指令,如您在官方CoreFX存储库中所见:

Source Code of Unsafe.As

答案 5 :(得分:-3)

更改此行:

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

对于这一行:

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