2012-12-28 11 views
8

一つは集合型の内部に格納されている列挙されている場合、いずれかのタイプのハッシュコードの内部(典型的な「multiply by primes」ハッシュ関数を仮定して)ことを含めることができます。ただSomeEnum.GetHashCode()を呼び出すと、リリースビルドでもJITがインスタンスを囲むように見えます。このプロファイリング列挙体のハッシュコードをボックス化せずに取得するにはどうすればよいですか?

は自分のアプリケーションの時間の約10%は、様々なGetHashCode関数の内部ボクシングの列挙を過ごした示しています。

IEquatableまたは類似のインターフェイスを実装するいくつかの値タイプは、GetHashCodeを静的メソッドとして呼び出すことができます。ボクシングを避ける。しかし、System.Enumは、GetHashCodeの静的過負荷を提供しません。使用すべきであるが、ボクシングを避けるコードを計算するいくつかの手段はありますか?

+2

なぜ全然気に? enumは独自のハッシュコードです。ちょうどintにキャストし、それを1日と呼んでください。 –

+0

@レイモンド:私はそれが悪い分布をもたらすかもしれないと思った。それをもう一度考え直すと、それがうまくいくかどうかわかります。 –

+0

@Raymond:確かに、この特定のテストケースではうまくいきます。私は –

答えて

4

あなたは(列挙型の定義に特別な指示がない限り、通常はint)列挙型の基になる型にキャストし、そのタイプの上書きGetHashCode()メソッドを使用することができます。ここで

enum TestEnum 
{ 
    Test1, 
    Test2 
} 

TestEnum t = TestEnum.Test1; 
((int)t).GetHashCode(); // no boxing 
t.GetHashCode(); // boxing 

は、このコードのためのILです:

IL_0000: nop 
IL_0001: ldc.i4.0 
IL_0002: stloc.0 
IL_0003: ldloc.0 
IL_0004: stloc.1 
IL_0005: ldloca.s V_1 
IL_0007: call  instance int32 [mscorlib]System.Int32::GetHashCode() 
IL_000c: pop 
IL_000d: ldloc.0 
IL_000e: box  ConsoleApplication1.Program/TestEnum 
IL_0013: callvirt instance int32 [mscorlib]System.Object::GetHashCode() 
IL_0018: pop 
IL_0019: ret 

編集:完全性についてはは、私がint.GetHashCode()の体はので、単にreturn this;であることを指摘すべきであるレイモンド・チェンがで指摘したように上記のコメントは、enumを単にintにキャストするだけで十分です。ハッシュコードを取得するには十分です。

+0

これは実際にボクシングを避けていますか? (例えば 'int.GetHashCode()もボクシングの結果にならない?) –

+0

はい、これはボクシングを避けます。 enumからintへのキャストはボクシングを避けます(Jon Skeetの最初のコメントhttp://bytes.com/topic/c-sharp/answers/276556-enum-vs-constants-performance参照)、intでGetHashCodeを呼び出すとGetHashCodeがこの構造体のためにオーバーライドされて以来、ボクシングの原因にはなりません(私はその実装を逆コンパイルし、ボクシング操作を引き起こす何もしません)。 GetHashCodeのEnumバージョンを呼び出すと、 'object'を返す内部メソッドが呼び出され、その上で' GetHashCode() 'が呼び出されるため、実際にボクシングが発生します(前述したように)。 – jam40jeff

+0

ところで、私は誤って 'GetHashCode()'の実装をチェックしていました。 'int'の実装は単純に' return this; 'なので、(Raymond Chenがコメントしたように)Enumの値を' int'にキャストし、それをあなたのハッシュコードとして使うことができます。 – jam40jeff

関連する問題