为什么我不能将`this`强制转换为泛型?
我有一个问题,包装我的头为什么没有编译以下代码片段。为什么我不能将`this`强制转换为泛型?
的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();
}
}
编译器告诉你到底发生了什么错误:你不能隐含地将SomeClass
转换为T
,但是确实存在两件事你需要注意。
首先,您不能隐式转换为泛型类型,因为在编译时该类型是未知的。您必须明确地投射它,或者 - 如果您确实需要隐式转换 - 请使用继承。
第二件事是需要更多的类型信息(通过约束)来区分值类型和引用类型。现在编译器知道什么都没有约T
。它可能是一个int
,其中一个class
永远不能被转换。
为引用类型强制转换为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
投到T
,其作品出于同样的原因。您正在规避编译时检查。
你可以这样做,然后打电话给someClassInstance.Coerce<int>()
,它会给你例外“指定的转换无效”。在运行时间。但是,使用通用约束会在编译时间处给出警告。
如果这并不妨碍你,return (dynamic)this;
是一个更简单的解决方案。但这种做法有悖于使用泛型的目的。
但是为什么'return(T)(object)this;'没有约束的工作? –
这只是一种欺骗编译器的方式,与使用'dynamic'非常密切相关(如果不转换为正确的类型,将导致令人讨厌的运行时错误)。一个对象可以是任何东西:值类型或引用类型(因为这个原因你不能使用'object'作为通用约束条件) –
更新我的答案,更详细地解释这些不同方法的含义 –
如果你解释了你在这里实现的目标,这可能会有所帮助。 –
'return(T)(object)this;' – PetSerAl
你为什么要这样做? –