我遇到了一个问题,为什么下面的代码段都没有编译。
Visual Studio将第一个标记为:
无法将'SomeType'类型转换为'T'
施法是多余的。
using System;
public class SomeClass {
public T Coerce<T>() {
if (typeof(T) == typeof(SomeClass))
return (T)this; // <- Error CS0030
else throw new InvalidCastException();
}
}
然后,删除“冗余”强制转换只会将错误更改为:
无法将类型'SomeOtherClass'隐式转换为'T'
using System;
public class SomeOtherClass {
public T Coerce<T>() {
if (typeof(T) == typeof(SomeOtherClass))
return this; // <- Error CS0029
else throw new InvalidCastException();
}
}
答案 0 :(得分:2)
编译器告诉你到底出了什么问题:你无法隐式地将SomeClass
转换为T
,但实际上有两件事你需要注意。
首先,您不能隐式转换为泛型类型,因为在编译时不知道该类型。你必须明确地转换它 - 如果你真的需要隐式转换 - 使用继承。
第二件事是需要更多类型信息(通过约束)以区分值类型和引用类型。现在,编译器知道关于T
的无。它也可能是int
,class
永远不会被投射到。{/ p>
为了将引用类型转换为T
,您需要class
约束,它将正常工作:
public class SomeClass
{
public T Coerce<T>() where T : class
{
if (typeof(T) == typeof(SomeClass))
return this as T;
else throw new InvalidCastException();
}
}
现在编译器也会阻止你做someClassInstance.Coerce<int>()
这样的事情,这就是重点。
修改强>:
至于(T)(object)this
的示例,这是有效的,因为您不再将this
投射到T
。相反,您将this
投射到object
(这将永远有效,因为它是所有其他类型派生自的),然后您从object
投射到{{ 1}}这也是出于同样的原因。您正在规避编译时检查。
您可以执行此操作然后调用T
,它会为您提供异常“指定的强制转换无效”。在运行时。但是,使用通用约束会在编译时时为您提供警告。
如果这不打扰你,someClassInstance.Coerce<int>()
是一个更简单的解决方案。但这有点违背了使用泛型的目的。