你能解释为什么第一行代码会给我编译错误而下一行代码却没有。
public void DoStuff<T>(T obj)
{
Int32 x = (Int32) obj; // 1. Error
Int32 y=(Int32)(Object)obj; //2. Works fine
}
答案 0 :(得分:4)
为了进行强制转换,您需要在编译时知道如何从一种类型转换为另一种类型。例如:
long l = 34;
int i = (int)l;
这是有效的,因为编译器知道如何将long
转换为int
。它还知道如何将object
转换为int
:
object o = 42;
int i = (int)o;
但是,并非所有类型都可以投射到int
:
string s = "48";
int i = (int)s; // This will not compile.
由于您的通用符可以表示任何类型,因此您不能仅为任何类型强制转换为int
。你必须先把它投射到可以投射到int
的东西上。因为任何东西都可以投射到object
和object
并被投射到任何东西,所以你的双重投射会起作用。
答案 1 :(得分:0)
将泛型类型变量转换为其他类型是非法的,除非您要转换为与约束兼容的类型:
private static void CastingAGenericTypeVariable1<T>(T obj) {
Int32 x = (Int32) obj; // Error
String s = (String) obj; // Error
}
编译器在上面的两行上都发出错误,因为T可以是任何类型,并且没有 保证演员阵容成功。您可以通过首先转换为Object来修改此代码以使其编译:
private static void CastingAGenericTypeVariable2<T>(T obj) {
Int32 x = (Int32) (Object) obj; // No error
String s = (String) (Object) obj; // No erro``r
}
虽然此代码现在将编译,但CLR仍可能在运行时抛出InvalidCastException。
如果您尝试强制转换为引用类型,则还可以使用C#作为运算符。这里修改了代码以使用带字符串的as运算符(因为Int32是值类型):
private static void CastingAGenericTypeVariable3<T>(T obj) {
String s = obj as String; // No error
}
This is from CLR via C#
答案 2 :(得分:0)
T
可以是任何类型,但编译器会识别出对Int32
的强制转换仅适用于某些类型,因此编译错误。
答案 3 :(得分:0)
如果你有一个泛型方法,你可能不想转换为int。通过重载或其他方法几乎可以肯定有更好的方法。
但是......如果您决定需要这样做,您可以安全地执行以下两种方法中的任何一种......
if (obj is Int32)
{
// do stuff
}
或..
Int32? z = obj as Int32?
if (z != null)
{
// do stuff
}
答案 4 :(得分:0)
规范解释了这种行为:
6.2.7涉及类型参数的显式转换
以上规则不允许直接显式转换 非约束类型参数到非接口类型,可能是 奇怪。这个规则的原因是为了防止混淆和制造 这种转换的语义清晰。例如,考虑一下 以下声明:
class X<T>
{
public static long F(T t) {
return (long)t; // Error
}
}
如果允许将t直接显式转换为int,则为1 可能很容易预期X.F(7)将返回7L。但是,它 不会,因为标准的数字转换只是 当绑定时已知类型为数字
时考虑