GetHashCode()
そのため、VB で多数のカスタム オブジェクトを正しくオーバーライドする方法を見つけようとしています。少し検索すると、この素晴らしい答えにたどり着きます。
ただし、問題が 1 つあります。VBには、.NET 4.0のchecked
andキーワードがありません。unchecked
とにかく、私が知る限り。Name As String
そこで、Jon Skeet の実装を使用して、Value As Int32
、 、の 3 つの主要メンバーを持つかなり単純なクラスで、このようなオーバーライドを作成しようとしました[Type] As System.Type
。したがって、私は思いつきます:
Public Overrides Function GetHashCode() As Int32
Dim hash As Int32 = 17
hash = hash * 23 + _Name.GetHashCode()
hash = hash * 23 + _Value
hash = hash * 23 + _Type.GetHashCode()
Return hash
End Function
問題: このような単純なオブジェクトでさえ、Int32 は小さすぎます。私がテストした特定のインスタンスには、単純な 5 文字の文字列として「名前」があり、そのハッシュだけでも Int32 の上限に十分近く、ハッシュの 2 番目のフィールド (値) を計算しようとすると、オーバーフローしました。checked
グラニュラー/サポートに相当する VB が見つからないため、unchecked
これを回避することはできません。
また、プロジェクト全体で整数オーバーフロー チェックを削除したくありません。これはおそらく....40% 完了しています (私が作成したものです、TBH)。さらに多くのコードを記述する必要があるため、これらのオーバーフロー チェックをかなりの時間行う必要があります。
GetHashCode
VB および Int32 用の Jon のバージョンの「安全な」バージョンは何でしょうか? または、.NET 4.0 には、MSDN で簡単に見つけられない
checked
/が含まれていますか? 編集:
リンクされたSOの質問ごとに、一番下にある愛されていない回答の1つが準解決策を提供しました。準と言うのは、それが…不正行為のように感じるからです。物乞いは選ぶ人になれませんよね?unchecked
C# からより読みやすい VB に変換し、上記のオブジェクト (名前、値、型) に合わせると、次のようになります。
Public Overrides Function GetHashCode() As Int32
Return New With { _
Key .A = _Name, _
Key .B = _Value, _
Key .C = _Type
}.GetHashCode()
End Function
これにより、コンパイラは匿名型を生成することで明らかに「チート」を開始し、おそらく整数オーバーフロー チェックを無効にして、プロジェクトの名前空間の外部でコンパイルし、計算を実行して、オーバーフローしたときにラップ アラウンドすることができます。またbox
、パフォーマンス ヒットであることがわかっているオペコードも関係しているようです。ただし、開封はありません。
しかし、これは興味深い問題を提起します。ここや他の場所で、VB と C# の両方が同じ IL コードを生成すると述べているのを数え切れないほど見てきました。これは明らかに 100% の場合ではありません...C# の </修辞的質問>unchecked
キーワードを使用すると、別のオペコードが発行されるだけです。では、両方がまったく同じ IL を生成するという仮定が繰り返され続けるのはなぜでしょうか?
とにかく、各オブジェクト モジュール内で実装できるソリューションを見つけたいと思います。オブジェクトごとに匿名型を作成しなければならないことは、ILDASM の観点からは面倒に見えます。プロジェクトに多くのクラスが実装されて
いると言っても冗談ではありません。
EDIT2: MSFT Connect のバグを公開しました。VB PM の結果の要点は、彼らがそれを検討するということでしたが、息を止めないでください:
https://connect.microsoft.com/VisualStudio/フィードバック/詳細/636564/checked-unchecked-keywords-in-visual-basic
.NET 4.5 の変更点をざっと見てみると、まだ検討していないことがわかります。おそらく .NET 5 でしょうか?
GetHashCode の制約に適合し、 VB にとって十分に高速でユニークな私の最終的な実装は、このページの「回転ハッシュ」の例から派生したものです。
'// The only sane way to do hashing in VB.NET because it lacks the
'// checked/unchecked keywords that C# has.
Public Const HASH_PRIME1 As Int32 = 4
Public Const HASH_PRIME2 As Int32 = 28
Public Const INT32_MASK As Int32 = &HFFFFFFFF
Public Function RotateHash(ByVal hash As Int64, ByVal hashcode As Int32) As Int64
Return ((hash << HASH_PRIME1) Xor (hash >> HASH_PRIME2) Xor hashcode)
End Function
また、「Shift-Add-XOR」ハッシュも適用される可能性があると思いますが、テストしていません。