【发布时间】:2015-12-12 23:22:37
【问题描述】:
我了解不能将基类转换为派生类。我不明白的是为什么这在编译时没有被捕获?例如:
class GradeBook
{
}
class ProfessorGradeBook : GradeBook
{
}
class Program
{
static void Main(string[] args)
{
ProfessorGradeBook a = (ProfessorGradeBook)new GradeBook();
//shouldn't this be a compile time error?
}
}
我已经查看了有关 stackoverflow 的其他问题,但对我来说仍然没有意义,为什么这会编译? ProfessorGradeBook a = (ProfessorGradeBook)new GradeBook(); 在任何情况下都不会成功(对吗?)那么为什么这是运行时错误而不是编译时错误?
编辑:
我已经知道为什么编译器永远不会捕捉到这个:
GradeBook a = new ProfessorGradeBook();
ProfessorGradeBook b = (ProfessorGradeBook)a;
在运行时,a 可能指向任何东西,因此编译器应该信任您。我更关心为什么编译器永远不会捕捉到这个:
ProfessorGradeBook a = (ProfessorGradeBook)new GradeBook();
我想最有意义的答案是 Eric Lippert 的第一条评论,特别是“绝大多数开发人员永远不会键入那行代码”,因此编译器团队从不担心试图让那行代码出错。
【问题讨论】:
-
这不是编译问题,因为编译器将 2 个命令分开。首先它创建了一个新的 GradeBook 实例,然后他尝试从基础对象投射一个对象,这也很好。编译器并不“知道”这个对象实际上只是一个基础对象。
-
简而言之:编译器团队可能会花费时间和精力来制作警告或错误。花费有限精力的目标是解决真正的开发人员实际遇到的实际问题。一个明确的非目标是在编译时发现任何可能的错误。编译器很容易对此给出警告。这不是因为绝大多数开发人员一开始就不会输入它。永远不会触发的警告,因为没有人键入该代码是浪费精力,可以花在设计更有用的警告上。
-
更具体地说,强制转换运算符在这里有一个非常具体的含义;它的意思是“注意编译器,我正在编写你无法证明是类型安全的代码。我知道它是类型安全的;相信我,并允许此代码编译。如果我错了,请让我的程序崩溃 " 也就是说,演员明确关闭安全系统。当您关闭错误检测系统时,编译器没有给出错误几乎不能怪罪!当您编写转换时,您负责确保转换成功,而不是编译器!
标签: c#