【发布时间】:2013-02-15 22:19:32
【问题描述】:
出于好奇,为什么编译器对待不受约束的泛型类型与 typeof(object) 有任何不同?
class Bar { }
class Foo
{
void foo(object thing)
{
((Bar)thing).ToString();
}
}
class Foo<T>
{
void foo(T thing)
{
((Bar)thing).ToString();
}
}
在上面,将“T thing”转换为 Bar 会导致编译器错误。然而,将“对象事物”转换为 Bar 是编译器允许我做的事情,当然风险自负。
我不明白为什么。毕竟在 .net 中的对象是一个包罗万象的对象,运行时类型可以是装箱的值或任何类型的对象。所以我看不出编译器有什么逻辑理由来区分这两种情况。我能做的最好的事情是“程序员希望编译器对泛型类型进行类型检查,而不是对对象进行类型检查”。 :) 仅此而已吗?
顺便说一句,我知道我仍然可以在 Foo 案例中完成我的演员表,只需编写
((Bar)(object)thing).ToString();
我只是想了解编译器为什么会这样......
【问题讨论】:
-
将
int转换为Bar在编译时是否合法?当您使用int填写该类型参数时,它是否应该然后 开始出现编译器错误?如果组件不是你的,所以你看不到问题怎么办? T 不是对象。这是非常具体的事情。 -
您是否也知道您可以说
class Foo<T> where T : Bar以确保T始终可以转换为Bar? -
我确信 Eric Lippert 在某处有一篇关于此的博文,但我找不到...
-
您遇到的问题是您认为 T 意味着任何东西,而它实际上意味着非常具体的东西,但尚未指定。
-
由于将装箱值类型转换为任何引用类型都会导致错误,因此真正的问题肯定是编译器没有(通用)方法来区分装箱值类型和引用类型;因为如果可以的话,它肯定会为来自
object的此类转换引发编译时错误,即使在没有泛型的情况下也是如此。