web-dev-qa-db-ja.com

C#潜在的な面接の質問…難しすぎる?

このコードを実行せずに、呼び出される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

18
FlySwat

私はこれを面接の質問としては実際には使用しません。私は答えとその背後にある理由を知っていますが、このようなことがめったに出てこないので、問題にはならないはずです。答えを知っていても、候補者のコーディング能力についてはあまりわかりません。

A.Fooが仮想であり、Bがそれをオーバーライドした場合でも、同じ動作が得られることに注意してください。

C#のパズルや奇妙なものが好きなら、 私もいくつか持っています(これを含む)

56
Jon Skeet

あまりにもハード?いいえ、しかし質問のあなたの目標は何ですか?面接対象者から何を期待していますか?彼らがこの特定の構文上の癖を知っていること?それは、彼らが仕様/言語をよく研究した(彼らにとって良い)か、この問題に遭遇したことを意味します(うまくいけば、彼らが書いたものからではなく、彼らがやった場合は-そうです)。どちらの場合も、確かなプログラマー/エンジニア/アーキテクトが手元にあることを実際に示しているわけではありません。重要なのは質問ではなく、質問を取り巻く議論だと思います。

候補者に面接するとき、私は通常、言語のセマンティックな癖に基づいた一見単純な質問をしますが、そのセマンティックな癖によって私が見つけることができる多くの道を開くことができるので、面接対象者がそれを知っているかどうかは気にしません私の候補者が系統だった場合、彼らのコミュニケーションスタイル、「わからない」と言っても構わないと思っている場合、彼らは自分の足で考えることができますか、言語設計とマシンアーキテクチャを理解していますか、プラットフォームと移植性を理解していますか問題-要するに、私はすべてが「彼らはそれを手に入れますか?」につながる多くの成分を探しています。このプロセスには1時間以上かかります。

結局、私は彼らが私の質問に対する答えを知っているかどうかを実際には気にしません-質問は、私が質問することなく、その情報の残りすべてを間接的に取得できるようにするための策略です。この質問に貴重な裏技がない場合は、質問することすら気にしないでください。あなたは自分の時間と候補者の時間を無駄にしているのです。

26
plinth

そこでジョエルにこれ以上同意できませんでした。私は20年以上のデザインとコーディングの経験があり、それを見たときに最初に思いついたのは、コンパイルすらしないということでした。

単一のデータ型のみが異なるオーバーロードを回避しようとし、コードを見るとint/doubleの違いさえ認識しなかったため、この仮定を行いました。 Bで再定義できるようにするには、新しい演算子が必要だと思いました。

実際、私は、メソッドの1つに8つの異なるオーバーロードがあり、そのうちの2つは最後の引数のデータ型のみが異なるため、テキストファイルの生成を処理するために作成したライブラリを使用していました。 1つは文字列で、もう1つは文字です。パラメータの文字列バージョンに必要な値が1文字の長さである可能性はかなり高かったので、これがどこに向かっているのかがわかるといいのですが。ライブラリの利用者が、シングルとダブルの違いを引用しているために誤って間違った呼び出しをトリガーしたため、問題をデバッグするのに時間の悪魔がありました。

話の教訓は、それが良いコーディング習慣を示しているかもしれないので、候補者が答えを知らないことに感謝してください。

12
Bill

それを使用することに反対する別の投票が、別の理由で。

このようにその場に置くと、多くの本当に優秀なプログラマーが間違った答えを思い付くでしょうが、それは彼らが概念を知らないか、それを理解できなかったからではありません。何が起こるかというと、彼らはこのようなものを見て、「ああ、トリック質問!」と考えてから、応答で自分自身を考え抜くことに進みます。これは、IDEまたはGoogleや、プログラマーが日常のプログラミングで当たり前と思っている他の支援の恩恵を受けていないインタビューの設定で特に当てはまります。

10
Joel Coehoorn

Console.WriteLine( "B :: Foo");

自動的にキャストし、継承を進めずに最初のものを使用するためです。

面接の質問としては良いとは思いませんが、コードをコンパイルせずに解決しようとすると面白いかもしれません。

7

これは実際にはトリックの質問です。

何が「起こるべきか」についての答えはあいまいです。確かに、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#プログラマーがC#に準拠していないためにVB.NETを「bash」する機会を開いていることを認識しています。しかし、ここで適切な解釈を行っているのはVB.NETであるという非常に強い議論をすることができると思います。

さらに、C#内のIntelliSense IDEは、クラスBに2つのオーバーロードがあることを示唆しています(存在するか、少なくとも存在する必要があるためです!)が、B.Foo(int n)バージョンは実際には呼び出すことはできません(最初にクラスAに明示的にキャストする必要があります)。その結果、C#IDEは実際にはC#コンパイラと同期していません。

これを見る別の方法は、C#コンパイラが意図されたオーバーロードを取得し、それをシャドウメソッドに変換していることです。 (これは私には正しい選択ではないようですが、これは明らかに単なる意見です。)

面接の質問として、ここで問題について話し合うことに興味があれば大丈夫だと思います。 「正しい」または「間違っている」ということに関しては、間違った理由で簡単に見落とされたり、正しくなったりする可能性のあるトリック質問に近づいていると思います。実際、「あるべき」という質問に対する答えは、実際には非常に議論の余地があります。

5
Mike Rosenblum

面接の質問としては、ちょっとしたトリックの質問なので、あまり公平ではありません。インタビュイーに私が望む良い答えは、"リファクタリングが必要"の線に沿ったものになるでしょう。

コンパイラーの作業に誰かを雇うことを考えているのでない限り、CLRについてそれほど深く掘り下げる必要があるかどうかはわかりません。

面接の質問については、回答の中でコーダーの理解度を示すものを探します。これはもっと奇妙な/パズルです。

5
Keith

それはばかげた質問です-スニペットコンパイラで60秒未満で答えることができました。機能に依存するコードベースで作業したことがあれば、すぐにリファクタリングされて存在しなくなります。

最良の答えは、「それはばかげた設計です。そうしないでください。言語仕様を解析して、それが何をするのかを知る必要はありません」です。

私がインタビュイーだったとしたら、あなたのオタクトリビアの信用を非常に高く評価し、おそらくオタクトリビアル追求の次のゲームにあなたを招待するでしょう。しかし、私はあなたと一緒に/あなたのために働きたいかどうかはわかりません。それがあなたの目標であるならば、ぜひ遠ざけてください。

  • 非公式な状況では、このようなオタクの雑学クイズは楽しくて面白いことがあることに注意してください。しかし、面接対象者にとって、面接は面白くも非公式でもありません。真剣に受け止めているかどうかわからない些細な質​​問で、面接をさらに刺激するのはなぜですか。
3
Mark Brackett

ひどい質問だと思います。本当の答えが「実行して見てください」である場合、どんな質問もひどい質問だと思います。

実生活でこれを知る必要がある場合は、まさにそれを実行します。テストプロジェクトを作成し、キー入力して、調べます。そうすれば、抽象的な推論やC#仕様の細かい点について心配する必要はありません。

ちょうど今日、私はそのような質問に遭遇しました:同じ型のDataTableに同じ行を2回入力すると、どうなりますか?行のコピーを1つ、または2つ?また、変更しても最初の行は上書きされますか?誰かに聞いてみようと思ったのですが、DataSetsを使ったテストプロジェクトを簡単に立ち上げて、小さなメソッドを書いてテストできることに気づきました。

回答:

...ああ、でも私があなたに言うなら、あなたは要点を見逃すでしょう。 :)重要なのは、プログラミングでは、これらを仮説として残す必要はなく、合理的にテストできる場合はすべきではないです。

ですから、それはひどい質問だと思います。衰退した記憶からそれを浚渫しようとする開発者や質問する開発者よりも、それを試してから知っている何が起こるかを開発者に雇うことを好まないでしょうか他の誰かと間違っているかもしれない答えを受け入れますか?

3
Ryan Lundy

これは私にとってトリックの質問のスマックです。この言語を十分長い間使用している場合は、おそらく問題に遭遇し、答えを知っているでしょう。しかし、どれくらいの長さで十分ですか?

それはまた、あなたの経歴があなたに不利に働くかもしれない場所の問題でもあります。 C++ではBの定義がAの定義を非表示にすることは知っていますが、C#でも同じように機能するかどうかはわかりません。実生活では、それが疑わしい領域であったことを知っていて、それを調べてみてください。インタビューでは、その場に置かれたので、推測しようとするかもしれません。そして、私はおそらくそれを間違えるでしょう。

2
Mark Ransom

候補者が何が起こるべきだと思うかを説明するときに、候補者が自分の思考プロセスを教えてくれると期待する場合にのみ、質問として使用してください。問題の実際のコードの正誤を気にする人-現実の世界では、候補者はこのようなコードを見つけ、それが機能していないことを見つけ、デバッガーと書き込みラインの呼び出しの組み合わせでデバッグするので、必要に応じて役に立たない質問です正しい答えを知っている(または推測している)候補者。

しかし、彼らが何が起こると思うかを説明できる人は、それは別の問題です。彼らがそれを間違えたとしても彼らを雇う。

2
gbjbaanb

実際の作業状況では、何が悪かったのかを理解するのに5秒かかります。コンパイル、テスト、おっと。

私は、誰かが優れた保守可能なコードを構築できるかどうかについて、はるかに心配しています。次のような質問をする

  • このためにどのように設計し、コードなしで単純な抽象的な設計を記述しますか。
  • これがオブジェクトデザインです。顧客が来て、これが欲しいと言いました。新しい設計を策定するか、要件が実際の顧客のニーズを満たさない理由について話し合います。
2
Lee Louviere

問題のコードはB::Fooを出力します。

0
Anwar

以下に示す同様のサンプルを試してください。

class Program
{
    class P
    {}
    class Q : P
    {}

    class A 
    { 
        public void Fee(Q q)
        {
            Console.WriteLine("A::Fee");
        }
    }

    class B : A 
    {   
        public void Fee(P p)
        {
            Console.WriteLine("B::Fee");
        }
    }

    static void Main(string[] args) 
    { 
        B b = new B();   
        /* which Fee is chosen? */  

        b.Fee(new Q());
        Console.ReadKey();
    }
}

コンパイラーは、パラメーターを暗黙的にキャストしてそのようなメソッドに一致させることができる場合、継承されたメソッド(基本型のメソッド)ではなく、その型の使用可能なメソッドに「b.Fee()」呼び出しをリンクすることを好むようです。つまりパラメータの暗黙的なキャストは、基本クラスのメソッドリンクよりも優先されます。

正直なところ、私は反対の方が直感的だと思います。なぜなら、私にとっては、継承されたメソッドは直接導入されたメソッドと同じくらい優れているからです。

0
Smullyan8

多くの人がすでに述べているように、私が誰かに面接するとき、候補者がコミュニケーションできるか、意味があり、他の人が簡単に理解できるコードを書くことができるか、維持できるコードなどを知りたいです。私は個人的に、提案されたようなエクササイズに時間を費やすのは好きではありません。代わりに、候補者が(通常のテキストエディタでも)自分でコードを記述し、そこからコードレビューや改善などに基づいてディスカッションを開始する演習を行いたいと思います。コンパイルするコードは必要ありません。コンパイラは最終的にその仕事をします。多くの人がこのアプローチに同意しないかもしれないことを私は知っていますが、これまでのところ、これが良い候補者を見つける最良の方法であることがわかりました。

0
beltry