如果不运行此代码,请确定Foo
将调用哪个方法:
class A { public void Foo( int n ) { Console.WriteLine( "A::Foo" ); } } class B : A { /* note that A::Foo and B::Foo are not related at all */ public void Foo( double n ) { Console.WriteLine( "B::Foo" ); } } static void Main( string[] args ) { B b = new B(); /* which Foo is chosen? */ b.Foo( 5 ); }
哪种方法?为什么?运行代码不会作弊.
我在网上发现了这个难题; 我喜欢它,我想我会把它用作面试问题......意见?
编辑:我不会判断候选人是否错了,我会用它作为一种方式来开展关于C#和CLR本身的更全面的讨论,这样我就可以很好地理解候选人的能力.
资料来源: http ://netpl.blogspot.com/2008/06/c-puzzle-no8-beginner.html
我真的不会用这个作为面试问题.我知道答案及其背后的原因,但是这样的事情应该很少出现,这应该不是问题.知道答案确实没有表明候选人的编码能力.
请注意,即使A.Foo是虚拟的并且B覆盖它,您也会获得相同的行为.
如果你喜欢C#谜题和奇怪,我也有一些(包括这个).
太难?不,但问题的目标是什么?你期望从你的受访者那里得到什么?他们知道这个特殊的句法怪癖吗?这要么意味着他们已经很好地研究了规范/语言(对他们有利),或者他们遇到了这个问题(希望不是他们所写的,但是如果他们这样做的话 - 那么).这两种情况都没有真正表明你手上有一个可靠的程序员/工程师/建筑师.我认为重要的不是问题,而是围绕这个问题的讨论.
当我采访候选人时,我经常会问一个基于语言语义怪癖的看似简单的问题 - 但我不在乎我的受访者是否知道它,因为语义怪癖让我开辟了许多途径让我找到如果我的候选人是有条不紊的,他们的沟通方式,如果他们愿意说"我不知道",他们是否有能力自我思考,他们是否理解语言设计和机器架构,他们是否理解平台和便携性问题 - 简而言之,我正在寻找许多成分,这些成分都加起来"他们得到了吗?".此过程需要一个小时或更长时间.
最后,我实际上并不关心他们是否知道我的问题的答案 - 问题是让我间接得到所有其他信息而不必询问的诡计.如果你在这个问题上没有一个有价值的问题,那就不要再费心了 - 你在浪费时间和候选人的时间.
在那里与乔尔达成一致.我有20多年的设计和编码经验,当我看到它时,我想到的第一件事是:它甚至不会编译.
我做了这个假设,因为我试图避免只有一种数据类型不同的重载,并且在查看代码时甚至没有获得int/double差异; 我假设需要一个新的运算符来允许在B中重新定义.
事实上,我使用了一个库,一个程序员用来处理一些文本文件生成,这有点令人困惑,因为其中一个方法有8个不同的重载,其中两个只有最后一个参数的数据类型不同.一个是字符串,一个是char.参数的字符串版本所需的值是一个字符长度的可能性非常好,所以希望你能看到它的发展方向.我们有一个时间调试问题的恶魔,因为库的消费者无意中触发了错误的调用,因为引用了差异,单一与双重.
故事的道德,感谢候选人不知道答案,因为它可能表明良好的编码习惯.
另一次投票反对使用它,但出于不同的原因.
当像这样放在现场时,许多真正优秀的程序员会想出错误的答案,但不是因为他们不知道这些概念或者无法弄明白.会发生什么事情,他们会看到这样的事情,然后思考,"啊哈,技巧问题!",然后继续思考自己的反应.在面试环境中尤其如此,他们没有IDE或Google或其他任何其他帮助程序员在日常编程中认为理所当然的好处.
Console.WriteLine("B :: Foo");
因为它将自动转换并使用第一个而不进一步继承.
我不认为这是一个很好的面试问题,但尝试解决而不编译代码会很有趣.
这实际上是一个棘手的问题.
关于"应该"发生什么,答案是模棱两可的.当然,C#编译器将其从具体模糊性的范围中解脱出来; 但是,由于这些方法彼此重载,并且既不是覆盖也不是阴影,所以可以合理地假设"最佳参数拟合"应该适用于此,因此得出结论:它应该是A :: Foo(int n)在提供整数作为参数时调用.
为了证明"应该"发生的事情尚不清楚,在VB.NET中运行时完全相同的代码会产生相反的结果:
Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles Button1.Click Dim b As New B b.Foo(5) ' A::Foo b.Foo(5.0) ' B::Foo End Sub End Class Class A Sub Foo(ByVal n As Integer) MessageBox.Show("A::Foo") End Sub End Class Class B Inherits A Overloads Sub Foo(ByVal n As Double) MessageBox.Show("B::Foo") End Sub End Class
我意识到我正在为C#程序员提供机会"打击"VB.NET而不遵守C#.但我认为人们可以提出一个非常强烈的论点,即VB.NET正在这里做出正确的解释.
此外,C#IDE中的IntelliSense建议B类有两个重载(因为有,或者至少应该是!),但实际上不能调用B.Foo(int n)版本(不是没有第一个)显式地转换为A)类.结果是C#IDE实际上与C#编译器不同步.
另一种看待这种情况的方法是C#编译器正在进行预期的重载并将其转换为阴影方法.(这对我来说似乎不是正确的选择,但这显然只是一种意见.)
作为一个面试问题,我认为如果你有兴趣在这里讨论这些问题就可以了.至于让它"正确"或"错误",我认为这个问题接近一个可能很容易错过甚至是正确的技巧问题.事实上,问题"应该是"的答案实际上是非常值得商榷的.
作为面试问题并不公平,因为这是一个棘手的问题.我希望受访者得到的好答案更像是"需要重构".
除非你想聘请某人从事编译工作,否则我不确定你是否需要深入研究CLR.
对于面试问题,我会寻找能够在答案中显示编码人员理解水平的内容.这更像是一个奇怪/谜题.