"「C#できます」と言い放ったあいつがJavaプログラマであることを見分ける10の質問" をやってみる
実質はてなダイアリー初投稿。
「C#できます」と言い放ったあいつがJavaプログラマであることを見分ける10の質問 - 平々毎々(アーカイブ)が気になったので、やってみる。
はてな記法よくわかんない。
==演算子のオーバーロードを実装してEqualsメソッドと同じ処理を実行するようにしてもよい場合はどのような時か?
既定では、演算子 == は、2 つの参照が同じオブジェクトを示すかどうかを確認して参照の等価をテストします。したがって、この機能を取得するために参照型で演算子 == を実装する必要はありません。型が変更できない場合、つまりインスタンスに含まれているデータを変更できない場合、その型は、変更不可能なオブジェクトとして、同じ値を持つ限り同一と見なされるので、参照の等価の代わりに値の等価を比較するように演算子 == をオーバーロードするのが有効です。変更不可能な型以外で演算子 == をオーバーライドすることはお勧めしません。
Equals() と演算子 == のオーバーロードに関するガイドライン (C# プログラミング ガイド) | Microsoft Docs
なるほど。
- 結論: immutableな型の場合。
ループ内でなければ、たとえ100個の文字列型変数であってもまとめて+演算子で連結してよい理由を説明せよ
↓をReleaseでビルドしてildasmでILを確認。
using System; namespace StringConcatOptimization { class Program { static void Main(string[] args) { string a = "a"; string b = "b"; string c = "c"; string d = "d"; string e = "e"; string concatinated = a + b + c + d + e; Console.WriteLine(concatinated); } } }
はてなダイアリーも、さすがにMSILのシンタックスハイライトには対応していないっぽい。
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // コード サイズ 82 (0x52) .maxstack 3 .locals init ([0] string a, [1] string b, [2] string c, [3] string d, [4] string e, [5] string concatinated, [6] string[] CS$0$0000) IL_0000: ldstr "a" IL_0005: stloc.0 IL_0006: ldstr "b" IL_000b: stloc.1 IL_000c: ldstr "c" IL_0011: stloc.2 IL_0012: ldstr "d" IL_0017: stloc.3 IL_0018: ldstr "e" IL_001d: stloc.s e IL_001f: ldc.i4.5 IL_0020: newarr [mscorlib]System.String IL_0025: stloc.s CS$0$0000 IL_0027: ldloc.s CS$0$0000 IL_0029: ldc.i4.0 IL_002a: ldloc.0 IL_002b: stelem.ref IL_002c: ldloc.s CS$0$0000 IL_002e: ldc.i4.1 IL_002f: ldloc.1 IL_0030: stelem.ref IL_0031: ldloc.s CS$0$0000 IL_0033: ldc.i4.2 IL_0034: ldloc.2 IL_0035: stelem.ref IL_0036: ldloc.s CS$0$0000 IL_0038: ldc.i4.3 IL_0039: ldloc.3 IL_003a: stelem.ref IL_003b: ldloc.s CS$0$0000 IL_003d: ldc.i4.4 IL_003e: ldloc.s e IL_0040: stelem.ref IL_0041: ldloc.s CS$0$0000 IL_0043: call string [mscorlib]System.String::Concat(string[]) IL_0048: stloc.s concatinated IL_004a: ldloc.s concatinated IL_004c: call void [mscorlib]System.Console::WriteLine(string) IL_0051: ret } // end of method Program::Main
string[]型のローカル変数が自動的に作られ、それを使用してString.Concatの呼び出しが1回にまとめられている。
Listのように値型を格納するジェネリックコレクションを使ってもボックス化/ボックス化解除が発生しない理由を説明せよ
- 発生しないモノとして認識はしていたが、理由といわれても答えられない。
- オブジェクトが(ポインタでなく)直に格納されているからと言う事でいいのか?
- 仕様?
Full GC(Gen2 GC)が動作したときに断片化していてもコンパクションされないヒープ領域はどのような領域か?
- LOH (Large Object Heap)。
- 巨大オブジェクトを作った時は、ここに割り当てられる。
- 断片化の問題についての解説はここが詳しい。=> MSDN マガジンのバックナンバー | Microsoft Docs
throw; とthrow ex; の違いをスタックトレースの観点で説明せよ。
フィールドのアクセス修飾子をprivateにしプロパティのgetter/setterではそのフィールドを読み書きするだけというコードが馬鹿馬鹿しい理由を説明せよ。
- そういう場合は、自動実装プロパティを使用すれば、簡潔に記述できる。
nullを参照している参照型変数のメソッドを呼び出そうとした場合でもNullReferenceExceptionが発生しないのは主にどういう状況か?
- 拡張メソッドの場合?
- 拡張メソッドを "参照変数のメソッド" と呼べるのかがよくわからない。
クラスと構造体の違いは何か?(「スタックとヒープ」以外で)
- 変数へ代入する時にオブジェクトがコピーされる。
- ヒープを使わずスタックを使うので軽量だが、コピーのコストに注意する必要がある。
- ひとつの指標としては、16byteを超える場合はクラスにすべき。
インターフェースの明示的実装を利用する目的を1つ説明せよ。
- 同じ名前と引数の型を持のメソッドを持つ、複数のインターフェイス(例: IEnumerable
とIEnumerableは両方ともGetEnumerable()を持っている) を実装するため。
自信持って答えられたのは6/10。難しいです。