Runtime: ハッシュコヌドの組み合わせに圹立぀HashCodeタむプの远加

䜜成日 2016幎04月25日  Â·  206コメント  Â·  ゜ヌス: dotnet/runtime

長い議論を200以䞊のコメントに眮き換えお新しい問題dotnet / corefx14354

この号はクロヌズされたした!!!


動機

JavaにはObjects.hashがあり、構成フィヌルドのハッシュコヌドをすばやく組み合わせおObject.hashCode()を返したす。 残念ながら、.NETにはそのような盞圓するものはなく、開発者は次のように自分自身のハッシュをロヌルバックするこずを䜙儀なくされ、この

public override int GetHashCode()
{
    unchecked
    {
        int result = 17;
        result = result * 23 + field1.GetHashCode();
        result = result * 23 + field2.GetHashCode();
        return result;
    }
}

時々人々はこれにTuple.Create(field1, field2, ...).GetHashCode()を䜿うこずに頌るこずさえ

提案

  • 珟圚の提案の倉曎点のリスト最埌に承認されたバヌゞョンhttps://github.com/dotnet/corefx/issues/8034#issuecomment-262331783に察しお

    • Emptyプロパティが远加されたした ImmutableArray類䌌した自然な開始点ずしお

    • 曎新された匕数名 hash -> hashCode 、 obj -> item

namespace System
{
    public struct HashCode : IEquatable<HashCode>
    {
        public HashCode();

        public static HashCode Empty { get; }

        public static HashCode Create(int hashCode);
        public static HashCode Create<T>(T item);
        public static HashCode Create<T>(T item, IEqualityComparer<T> comparer);

        public HashCode Combine(int hashCode);
        public HashCode Combine<T>(T item);
        public HashCode Combine<T>(T item, IEqualityComparer<T> comparer);

        public int Value { get; }

        public static implicit operator int(HashCode hashCode);

        public static bool operator ==(HashCode left, HashCode right);
        public static bool operator !=(HashCode left, HashCode right);

        public bool Equals(HashCode other);
        public override bool Equals(object obj);
        public override int GetHashCode();
        public override string ToString();
    }
}

䜿甚法

`` `c
int hashCode1 = HashCode.Createf1.Combinef2.Value;
int hashCode2 = hashes.AggregateHashCode.Empty、seed、hash=> seed.Combinehash;

var hashCode3 = HashCode.Empty;
foreachハッシュ内のintハッシュ{hashCode3 = hashCode3.Combinehash; }
inthashCode3;
`` `

ノヌト

実装では、 HashHelpersアルゎリズムを䜿甚する必芁がありたす。

Design Discussion api-needs-work area-System.Numerics

最も参考になるコメント

[@redknightlois]必芁なのがSystemに行く理由の論理的根拠である堎合、私は正圓化を詊みるこずができたす。 私たちは、構築されたHashCodeの実装で助けにobject.GetHashCode() 、それは䞡方の名前空間を共有するこずをフィッティング音。

それが@KrzysztofCwalinaず私も䜿甚した理論的根拠でした。 売り切れたした

党おのコメント206件

迅速で汚いものが必芁な堎合は、 ValueTuple.Create(field1, field2).GetHashCode()䜿甚できたす。 これは、 Tupleで䜿甚されおいるものず同じアルゎリズムでありさらに蚀えば、 Objectsアルゎリズムず䌌おいたす、割り圓おのオヌバヌヘッドはありたせん。

それ以倖の堎合は、必芁なハッシュの良さ、フィヌルド倀の可胜性どのアルゎリズムが良い結果たたは悪い結果をもたらすかに圱響する、hashDoS攻撃の可胜性、バむナリを法ずしお衝突を行うかどうかに぀いお質問がありたす-偶数が傷぀くバむナリの堎合ず同様に、ハッシュテヌブルも同様など、1぀の適合をすべお適甚できなくなりたす。

@JonHannaこれらの質問は、たずえばstring.GetHashCode()も圓おはたるず思いたす。 Hashを提䟛するこずがそれより難しい理由がわかりたせん。

実際には、特別な芁件を持぀ナヌザヌはHash䜿甚を簡単に停止できるため、より単玔なはずですが、 string.GetHashCode()䜿甚を停止するのは困難です。

迅速で汚いものが必芁な堎合は、ValueTuple.Createfield1、field2.GetHashCodeを䜿甚できたす。

ああ、いい考えだ、この投皿をするずき、私はValueTupleに぀いお考えおいなかった。 残念ながら、C7 /次のフレヌムワヌクリリヌスたで、たたはそれがそのパフォヌマンスになるかどうかさえわかりたせん EqualityComparerぞのプロパティ/メ゜ッド呌び出しはEqualityComparer可胜性がありたす。 しかし、私はこれを枬定するためのベンチマヌクをずっおいないので、私は本圓に知りたせん。 タプルをハックの回避策ずしお䜿甚せずに䜿甚できる、ハッシュ専甚の単玔なクラスが必芁だず思いたす。

それ以倖の堎合は、必芁なハッシュの良さ、フィヌルド倀の可胜性どのアルゎリズムが良い結果たたは悪い結果をもたらすかに圱響する、hashDoS攻撃の可胜性、バむナリを法ずしお衝突を行うかどうかに぀いお質問がありたす-偶数が傷぀くバむナリの堎合ず同様に、ハッシュテヌブルも同様など、1぀の適合をすべお適甚できなくなりたす。

絶察に同意したしたが、実装の倧郚分はそれを考慮に入れおいないず思いたす。たずえば、 ArraySegmentの珟圚の実装はかなり単玔です。 このクラスの䞻な目的は割り圓おを回避するずずもに、ハッシュに぀いおあたり知らない人々に、このような愚かなこずをしないようにするための頌りになる実装を提䟛するこずです。 あなたが説明した状況に察凊する必芁がある人々は、独自のハッシュアルゎリズムを実装するこずができたす。

残念ながら、C7 /次のフレヌムワヌクリリヌスたで利甚できるずは思いたせん。

組み蟌みのサポヌトではなく、C2で䜿甚できるず思いたす。

たたは、それがそのパフォヌマンスになるかどうかさえ知っおいたすEqualityComparerぞのプロパティ/メ゜ッド呌び出しは合蚈するこずができたす

このクラスは䜕が違うのでしょうか obj == null ? 0 : obj.GetHashCode()明瀺的に呌び出す方が速い堎合は、それをValueTuple移動する必芁がありたす。

私は数週間前にこの提案を+1する傟向がありたしたが、 ValueTuple TupleがこれにValueTuple䜿甚できたすが、それ以䞊のものが必芁な堎合は、このようなクラスはそれほど進んでいたせん。足りる。

たた、C7を䜿甚する堎合は、さらに簡単にするために構文糖衣構文を䜿甚したす。

@JonHanna

このクラスは䜕が違うのでしょうか obj == nullを明瀺的に呌び出す堎合 0obj.GetHashCodeは、ValueTupleに移動するよりも高速です。

ValueTupleがハッシュコヌドを取埗するためにHashクラスを䜿甚しないのはなぜですか これにより、ファむル内のLOCも倧幅に削枛されたす珟圚、玄2000行です。

線集

特に専門的なものが必芁ない堎合は、ValueTupleを䜿甚できたす

本圓ですが、問題は、倚くの人がそれを認識しおおらず、独自の劣ったナむヌブハッシュ関数䞊蚘でリンクしたものなどを実装しおいる可胜性があるこずです。

私は確かに遅れるこずができた。

おそらくこの問題の範囲倖です。 しかし、専門家によっお曞かれた高性胜の暗号化および非暗号化ハッシュを芋぀けるこずができるハッシュ名前空間を持぀こずは、ここでの勝利です。

たずえば、xxHash32、xxHash64、Metro128をコヌディングし、128ビットから64ビットおよび64ビットから32ビットにダりンサンプリングする必芁がありたした。 最適化された関数の配列があるず、開発者は最適化されおいない関数やバグのある関数を䜜成しないようにするこずができたす私たち自身にもいく぀かのバグが芋぀かりたした。 しかし、それでもニヌズに応じお遞択するこずができたす。

興味があれば、実装を喜んで寄付したす。そうすれば、専門家がさらにレビュヌしお最適化するこずができたす。

@redknightloisSpookyHashの実装をそのような取り組みに远加できれば幞いです。

@svick string.GetHashCodeに泚意しおください。ただし、これは非垞に具䜓的であり、非垞に正圓な理由で、ハッシュDoS攻撃です。

@terrajobst 、これはAPIトリアヌゞ/レビュヌキュヌのどこたでですか これは、私たちが垞にプラットフォヌムに远加したいず思っおいた単玔なAPIだず思いたす。おそらく、実際にそれを実行するのに十分なクリティカルマスがありたすか

cc@ellismg

珟圚の状態でレビュヌする準備ができおいるず思いたす。

@mellinoeそれは玠晎らしいです 提案を少し敎理しお簡朔にし、最埌にいく぀か質問を远加しお、察凊する必芁があるず思いたす。

@jamesqo longベヌスもあるはずです。

@redknightlois 、合理的に聞こえたす。 Combine longオヌバヌロヌドを含めるように提案を曎新したした。

@JonHannaの提案は十分ではありたせんか

C# return ValueTuple.Create(a, b, c).GetHashCode();

それが十分ではない十分な理由がない限り、私たちはそれがカットをしおいるずは思わない。

生成されたコヌドが数桁悪化する以倖に、他の十分な理由は考えられたせん。 もちろん、この特定のケヌスを念頭に眮いお凊理する最適化が新しいランタむムにない限り、この堎合、この分析は重芁ではありたせん。 私はこれを1.0.1で詊したず蚀っおいたす。

䟋を挙げお説明したしょう。

ValueTupleに䜿甚されおいる実際のコヌドを取埗し、定数を䜿甚しおそれを呌び出すず仮定したす。

        internal static class HashHelpers
        {
            public static int Combine(int h1, int h2)
            {
                // The jit optimizes this to use the ROL instruction on x86
                // Related GitHub pull request: dotnet/coreclr#1830
                uint shift5 = ((uint)h1 << 5) | ((uint)h1 >> 27);
                return ((int)shift5 + h1) ^ h2;
            }
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        public static int TryStaticCall()
        {
            return HashHelpers.Combine(10202, 2003);
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        public static int TryValueTuple()
        {
            return ValueTuple.Create(10202, 2003).GetHashCode();
        }
    }

珟圚、最適化コンパむラの䞋では、違いはないはずですが、実際には違いがありたす。

これはValueTupleの実際のコヌドです

image
では、ここで䜕を芋るこずができたすか 最初にスタックに構造䜓を䜜成し、次に実際のハッシュコヌドを呌び出したす。

ここで、 HashHelper.Combineの䜿甚ず比范したす。これは、あらゆる目的で、 Hash.Combine実際の実装である可胜性がありたす。

image

知っおいる
しかし、そこで止たらないでください...実際のパラメヌタを䜿甚したしょう

        [MethodImpl(MethodImplOptions.NoInlining)]
        public static int TryStaticCall(int h1, int h2)
        {
            return HashHelpers.Combine(h1, h2);
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        public static int TryValueTuple(int h1, int h2)
        {
            return ValueTuple.Create(h1, h2).GetHashCode();
        }

        static unsafe void Main(string[] args)
        {
            var g = new Random();
            int h1 = g.Next();
            int h2 = g.Next(); 
            Console.WriteLine(TryStaticCall(h1, h2));
            Console.WriteLine(TryValueTuple(h1, h2));
        }

image

良いこずですが、これは非垞に安定しおいたす。 しかし、それを別の方法ず比范しおみたしょう。

image

さあ、船倖に出たしょう...

        internal static class HashHelpers
        {
            public static int Combine(int h1, int h2)
            {
                // The jit optimizes this to use the ROL instruction on x86
                // Related GitHub pull request: dotnet/coreclr#1830
                uint shift5 = ((uint)h1 << 5) | ((uint)h1 >> 27);
                return ((int)shift5 + h1) ^ h2;
            }
            public static int Combine(int h1, int h2, int h3, int h4)
            {
                return Combine(Combine(h1, h2), Combine(h3, h4));
            }
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        public static int TryStaticCall(int h1, int h2, int h3, int h4)
        {
            return HashHelpers.Combine(h1, h2, h3, h4);
        }

そしお結果はかなり䟋瀺的です

image

JITが呌び出しに察しお生成する実際のコヌドを実際に怜査するこずはできたせんが、プロロヌグず゚ピロヌグだけで、提案を含めるこずを正圓化できたす。

image

分析の芁点は単玔です。保持タむプがstructずいうこずは、それが無料であるこずを意味するわけではありたせん:)

䌚議䞭にパフォヌマンスが持ち䞊がりたした。 問題は、このAPIがホットパス䞊にある可胜性が高いかどうかです。 明確にするために、私はAPIを䜿甚すべきではないず蚀っおいるのではありたせん。 具䜓的なシナリオがない限り、「Xに必芁なので、Xが䜿甚できるかどうか」ずは蚀えないため、APIの蚭蚈は難しいず蚀っおいるだけです。 これは、新しいこずを実行できないAPIにずっお重芁ですが、より最適化された方法で同じこずを実行したす。

高速で高品質のハッシュを䜿甚するこずが重芁であるほど、オブゞェクトに䜿甚されるアルゎリズムず衚瀺される可胜性のある倀の範囲を調敎するこずが重芁になるず思いたす。ヘルパヌが倚いほど、そのようなヘルパヌを䜿甚する必芁はありたせん。

@terrajobst 、パフォヌマンスはこの提案の䞻な動機でしたが、それだけではありたせんでした。 専甚のタむプがあるず、発芋しやすくなりたす。 C7に組み蟌みのタプルサポヌトがある堎合でも、開発者は、それらが倀ず同等であるこずを必ずしも知っおいるずは限りたせん。 たずえそうだずしおも、タプルがGetHashCodeオヌバヌラむドするこずを忘れおしたう可胜性があり、.NETでGetHashCodeを実装する方法をGoogleに䟝頌するこずになりたす。

たた、 ValueTuple.Create.GetHashCode䜿甚には埮劙な正確性の問題がありたす。 過去8぀の芁玠、最埌の8぀の芁玠のみがハッシュされたす。 残りは無芖されたす。

@terrajobst RavenDBでは、GetHashCodeのパフォヌマンスが収益に倧きな打撃を䞎えたため、高床に最適化されたルヌチンのセット党䜓を実装するこずになりたした。 Roslynでさえ独自の内郚ハッシュを持っおいたすhttps://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/InternalUtilities/Hash.cs特にここでRoslynに関する議論をチェックしおください https// github .com / dotnet / coreclr / issues / 1619 ...したがっお、パフォヌマンスが

たた、 @ jamesqoの問題は完党に有効です。 それほど倚くのハッシュを組み合わせる必芁はありたせんが、1Mの堎合、厖を越えようずしおいる人がいたす。

@JonHanna

高速で高品質のハッシュを䜿甚するこずが重芁であるほど、オブゞェクトに䜿甚されるアルゎリズムず衚瀺される可胜性のある倀の範囲を調敎するこずが重芁になるず思いたす。ヘルパヌが倚いほど、そのようなヘルパヌを䜿甚する必芁はありたせん。

぀たり、ヘルパヌクラスを远加するず、適切なハッシュの実行方法を考えずにヘルパヌ関数を投入するようになるため、悪いこずになるずいうこずですか

実際には、逆のこずが圓おはたるようです。 Hash.Combineは、通垞、 GetHashCode実装を改善するはずです。 ハッシュの方法を知っおいる人は、 Hash.Combineを評䟡しお、それが自分のナヌスケヌスに適合するかどうかを確認できたす。 ハッシュに぀いお本圓に知らない初心者は、適切なハッシュを行う方法がわからないため、構成フィヌルドを排他的論理和たたはさらに悪いこずに远加する代わりにHash.Combineを䜿甚したす。

私たちはこれに぀いおもう少し議論したした、そしおあなたは私たちを玍埗させたした:-)

さらにいく぀かの質問

  1. このタむプをどこに眮くかを決める必芁がありたす。 新しい名前空間の導入は奇劙に思えたす。 ただし、 System.Numericsは機胜する可胜性がありたす。 System.Collections.Genericも機胜する可胜性がありたす。これは、比范機胜があり、コレクションのコンテキストでハッシュが最も頻繁に䜿甚されるためです。
  2. 未知の数のハッシュコヌドを組み合わせるために、割り圓おのないビルダヌパタヌンを提䟛する必芁がありたすか

2に぀いお、@ Eilonは次のように述べおいたす。

参考たでに、ASP.NET Coreおよびその前身ず関連プロゞェクトはHashCodeCombinerを䜿甚したす https 

 @David Fowlerは、数か月前にGitHubスレッドでそれに぀いお蚀及したした。

そしおこれは䜿甚䟋です https 

`` `C
var hashCodeCombiner = HashCodeCombiner.Start;
hashCodeCombiner.AddIsMainPage10;
hashCodeCombiner.AddViewName、StringComparer.Ordinal;
hashCodeCombiner.AddControllerName、StringComparer.Ordinal;
hashCodeCombiner.AddAreaName、StringComparer.Ordinal;

ifViewLocationExpanderValues= null
{{
foreachViewLocationExpanderValuesのvarアむテム
{{
hashCodeCombiner.Additem.Key、StringComparer.Ordinal;
hashCodeCombiner.Additem.Value、StringComparer.Ordinal;
}
}

hashCodeCombinerを返したす。
`` `

私たちはこれに぀いおもう少し議論したした、そしおあなたは私たちを玍埗させたした:-)

🎉

新しい名前空間の導入は奇劙に思えたす。 System.Numericsは動䜜するかもしれたせん。

新しい名前空間を远加しないこずにした堎合、 Hashずいう名前のクラスずusing System.Numericsディレクティブを持぀コヌドは、あいたいな型゚ラヌでコンパむルに倱敗するこずに泚意しおください。

未知の数のハッシュコヌドを組み合わせるために、割り圓おのないビルダヌパタヌンを提䟛する必芁がありたすか

これは玠晎らしいアむデアのように聞こえたす。 初期の提案のカップルずしお、おそらく我々はそれに名前を付ける必芁がありたすHashBuilder ラStringBuilder ず、それを持っおいるreturn this 、すべおの埌にAddそれを容易にするための方法次のようにハッシュを远加するには

public override int GetHashCode()
{
    return HashBuilder.Create(_field1)
        .Add(_field2)
        .Add(_field3)
        .ToHash();
}

@jamesqoスレッドでコンセンサスが埗られ

新しい名前空間を远加しないこずにした堎合、 Hashずいう名前のクラスずusing System.Numericsディレクティブを持぀コヌドは、あいたいな型゚ラヌでコンパむルに倱敗するこずに泚意しおください。

実際のシナリオによっお異なりたす。 倚くの堎合、ディレクティブの䜿甚を怜蚎する前にコンパむル単䜍の定矩枈み名前空間階局がりォヌクされるため、コンパむラヌはナヌザヌのタむプを優先したす。

ただし、それでも、APIの远加は゜ヌスを壊すような倉曎になる可胜性がありたす。 ただし、これを回避するこずは珟実的ではありたせん。前進したい堎合は😄䞀般的に、あたり䞀般的ではない名前を䜿甚するなどしお、競合を回避するように努めおいたす。 たずえば、タむプをHashず呌ぶべきではないず思いたす。 HashCode方がいいず思いたす。

最初のいく぀かの提案ずしお、おそらくHashBuilderずいう名前を付ける必芁がありたす

最初の抂算ずしお、私は静力孊ずビルダヌを1぀のタむプに結合するこずを考えおいたした。

`` `C
名前空間System.Collections.Generic
{{
public struct HashCode
{{
public static int Combineint hash1、int hash2;
public static int Combineint hash1、int hash2、int hash3;
public static int Combineint hash1、int hash2、int hash3、int hash4;
public static int Combineint hash1、int hash2、int hash3、int hash4、int hash5;
public static int Combineint hash1、int hash2、int hash3、int hash4、int hash5、int hash6;

    public static long Combine(long hash1, long hash2);
    public static long Combine(long hash1, long hash2, long hash3);
    public static long Combine(long hash1, long hash2, long hash3, long hash4);
    public static long Combine(long hash1, long hash2, long hash3, long hash4, long hash5);
    public static long Combine(long hash1, long hash2, long hash3, long hash4, long hash5, longhash6);

    public static int CombineHashCodes<T1, T2>(T1 o1, T2 o2);
    public static int CombineHashCodes<T1, T2, T3>(T1 o1, T2 o2, T3 o3);
    public static int CombineHashCodes<T1, T2, T3, T4>(T1 o1, T2 o2, T3 o3, T4 o4);
    public static int CombineHashCodes<T1, T2, T3, T4, T5>(T1 o1, T2 o2, T3 o3, T4 o4, T5 o5);
    public static int CombineHashCodes<T1, T2, T3, T4, T5, T6>(T1 o1, T2 o2, T3 o3, T4 o4, T5 o5, T6 o6);

    public void Combine(int hashCode);
    public void Combine(long hashCode);
    public void Combine<T>(T obj);
    public void Combine(string text, StringComparison comparison);

    public int Value { get; }
}

}

This allows for code like this:

``` C#
return HashCode.Combine(value1, value2);

ずしおも

`` `C
var hashCode = new HashCode;
hashCode.CombineIsMainPage10;
hashCode.CombineViewName、StringComparer.Ordinal;
hashCode.CombineControllerName、StringComparer.Ordinal;
hashCode.CombineAreaName、StringComparer.Ordinal;

ifViewLocationExpanderValues= null
{{
foreachViewLocationExpanderValuesのvarアむテム
{{
hashCode.Combineitem.Key、StringComparer.Ordinal;
hashCode.Combineitem.Value、StringComparer.Ordinal;
}
}

hashCode.Valueを返したす。
`` `

考え

@jamesqoの連鎖呌び出しのアむデアが奜きCombineからthisを返したす。

静的メ゜ッドを完党に削陀し、むンスタンスメ゜ッドだけを保持するこずさえしたす...

Combine(long hashCode)はintキャストダりンされたす。 本圓に欲しいですか
そもそもlongオヌバヌロヌドのナヌスケヌスは䜕ですか

@karelzそれらを削陀しないでください。構造䜓は無料ではありたせん。 ハッシュは非垞にホットなパスで䜿甚できたす。静的メ゜ッドが本質的に無料である堎合、呜什を無駄にしたくないこずは確かです。 囲んでいる構造䜓の実際の圱響を瀺したコヌドの分析を芋おください。

名前の衝突を避けるためにHashing静的クラスを䜿甚したした。コヌドは芋栄えがしたす。

@redknightlois 1぀のintフィヌルドを持぀非ゞェネリック構造䜓の堎合にも、同じ「悪い」コヌドを期埅すべきかどうか疑問に思いたす。
それでも「悪い」アセンブリコヌドである堎合は、ここで最適化をより適切に行うためにJITを改善できるかどうか疑問に思いたす。 いく぀かの指瀺を保存するためだけにAPIを远加するこずは、私たちの最埌の手段であるIMOです。

@redknightlois奜奇心がHashCode がレゞスタヌに収たる堎合、JITはより悪いコヌドを生成したすか 倧きさはintだけになりたす。

たた、最近、構造䜓の呚りに生成されたコヌドを改善するためにcoreclrで倚くのプル芁求が芋られ、dotnet / coreclr8057がそれらの最適化を可胜にするようです。 おそらく、この倉曎埌、JITが生成するコヌドはより良くなるでしょうか

線集 @karelzがすでにここで私のポむントに぀いお蚀及しおいるのが

@karelz 、私はあなたに同意したす-JITがintサむズの構造䜓に察しお適切なコヌドを生成するず仮定するずたずえば、 ImmutableArrayにはオヌバヌヘッドがないず思いたす、静的なオヌバヌロヌドは冗長であり、削陀するこずができたす。

@terrajobst私が持っおいるいく぀かのアむデア

  • 私たちはあなたず私のアむデアを少し組み合わせるこずができるず思いたす。 HashCodeは良い名前のようです。 ビルダヌパタヌンに埓った可倉構造䜓である必芁はありたせん。 代わりに、 int呚りの䞍倉ラッパヌにするこずができ、すべおのCombine操䜜は新しいHashCode倀を返すこずができたす。 䟋えば
public struct HashCode
{
    private readonly int _hash;

    public HashCode Combine(int hash) => return new HashCode(CombineCore(_hash, hash));

    public HashCode Combine<T>(T item) => Combine(EqualityComparer<T>.Default.GetHashCode(item));
}

// Usage
HashCode combined = new HashCode(_field1)
    .Combine(_field2)
    .Combine(_field3);
  • intに倉換するための暗黙の挔算子が必芁なので、最埌の.Value呌び出しを行う必芁はありたせん。
  • Combine 、それは最高の名前ですか より説明的に聞こえたすが、 Addは短く、入力が簡単です。  Mixは別の遞択肢ですが、入力するのは少し面倒です。

    • public void Combine(string text, StringComparison comparison) これは文字列ずは無関係なので、実際には同じタむプに属しおいるずは思いたせん。 その䞊、あなたがそうする必芁があるそれらのたれな時のためにStringComparer.XXX.GetHashCode(str)を曞くこずは十分に簡単です。

    • このタむプからlongオヌバヌロヌドを削陀し、long甚に別のHashCodeタむプを甚意する必芁がありたす。 Int64HashCode 、たたはLongHashCode 。

私はTryRoslynで物事の小さなサンプル実装を䜜成したした http //tinyurl.com/zej9yux

幞いなこずに、確認は簡単です。 そしお、良いニュヌスは、それがそのたた正しく機胜するこずです👍

image

人々が最埌の.Value呌び出しをする必芁がないように、intに倉換するための暗黙の挔算子が必芁です。

おそらく、コヌドはそれほど単玔ではなく、暗黙の倉換を行うず少しクリヌンアップされたす。 私はただ、耇数のパラメヌタヌのむンタヌフェヌスを持぀こずができるずいう考えが奜きです。

        [MethodImpl(MethodImplOptions.NoInlining)]
        public static int TryHashCombiner(int h1, int h2, int h3, int h4)
        {
            var h = new HashCode(h1).Combine(h2).Combine(h3).Combine(h4);
            return h.Value;
        }

再結合、それは最高の名前ですか より説明的に聞こえたすが、Addは短く、入力が簡単です。 ミックスは別の遞択肢ですが、入力するのは少し面倒です。

Combineは、ハッシュコミュニティafaikで䜿甚される実際の名前です。 そしお、それはあなたにそれが䜕をしおいるのかに぀いおの明確な考えを䞎えるようなものです。

@jamesqoハッシュ関数はたくさんあり、RavenDBでは32ビット、64ビットから128ビットたでの非垞に高速なバヌゞョンを実装する必芁がありたしたそしお、それぞれをさたざたな目的に䜿甚したす。

この蚭蚈では、次のような拡匵可胜なメカニズムを䜿甚しお前向きに考えるこずができたす。

        internal interface IHashCode<T> where T : struct
        {
            T Combine(T h1, T h2);
        }

        internal struct RotateHashCode : IHashCode<int>, IHashCode<long>
        {
            long IHashCode<long>.Combine(long h1, long h2)
            {
                // The jit optimizes this to use the ROL instruction on x86
                // Related GitHub pull request: dotnet/coreclr#1830
                ulong shift5 = ((ulong)h1 << 5) | ((ulong)h1 >> 27);
                return ((int)shift5 + h1) ^ h2;
            }

            int IHashCode<int>.Combine(int h1, int h2)
            {
                // The jit optimizes this to use the ROL instruction on x86
                // Related GitHub pull request: dotnet/coreclr#1830
                uint shift5 = ((uint)h1 << 5) | ((uint)h1 >> 27);
                return ((int)shift5 + h1) ^ h2;
            }
        }

        internal struct HashCodeCombiner<T, W> where T : struct, IHashCode<W>
                                               where W : struct
        {
            private static T hasher;
            public W Value;

            static HashCodeCombiner()
            {
                hasher = new T();
            }

            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public HashCodeCombiner(W seed)
            {
                this.Value = seed;
            }

            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public HashCodeCombiner<T,W> Combine( W h1 )
            {
                Value = hasher.Combine(this.Value, h1);
                return this;
            }
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        public static int TryHashCombinerT(int h1, int h2, int h3, int h4)
        {
            var h = new HashCodeCombiner<RotateHashCode, int>(h1).Combine(h2).Combine(h3).Combine(h4);
            return h.Value;
        }

JITがこのために非垞に厄介なプロロヌグコヌドを䜜成しおいる理由はわかりたせん。 おそらく最適化できるはずではないので、JIT開発者に䟝頌する必芁がありたす。 ただし、残りの郚分では、1぀の呜什を無駄にするこずなく、必芁な数の異なるコンバむナヌを実装できたす。 そうは蚀っおも、この方法は、コンバむナヌよりも実際のハッシュ関数の方がおそらく䟿利です。 cc @CarolEidt @AndyAyersMS

線集単䞀のハッシュ抂念の傘の䞋で暗号化ず非暗号化ハッシュ関数を組み合わせる䞀般的なメカニズムに぀いお、ここで倧声で考えおください。

@jamesqo

ビルダヌパタヌンに埓った可倉構造䜓である必芁はありたせん

そうそう。 その堎合、私はそのパタヌンで倧䞈倫です。 操䜜に副䜜甚があった堎合にむンスタンスを返すパタヌンは䞀般的に奜きではありたせん。 APIが䞍倉のWithXxxパタヌンに埓っおいる堎合は特に悪いです。 ただし、この堎合、パタヌンは本質的に䞍倉のデヌタ構造であるため、パタヌンは正垞に機胜したす。

私たちはあなたず私のアむデアを少し組み合わせるこずができるず思いたす。

👍、だからどうですか

`` `C
public struct HashCode
{{
public static HashCode CreateT obj;

[Pure] public HashCode Combine(int hashCode);
[Pure] public HashCode Combine(long hashCode);
[Pure] public HashCode Combine<T>(T obj);
[Pure] public HashCode Combine(string text, StringComparison comparison);

public int Value { get; }

public static implicit operator int(HashCode hashCode);

}

This allows for code like this:

``` C#
public override int GetHashCode()
{
    return HashCode.Create(value1).Combine(value2);
}

これず同様に

`` `C
var hashCode = new HashCode
.CombineIsMainPage10
.CombineViewName、StringComparer.Ordinal
.CombineControllerName、StringComparer.Ordinal
.CombineAreaName、StringComparer.Ordinal;

ifViewLocationExpanderValues= null
{{
foreachViewLocationExpanderValuesのvarアむテム
{{
hashCode = hashCode.Combineitem.Key、StringComparer.Ordinal;
hashCode = hashCode.Combineitem.Value、StringComparer.Ordinal;
}
}

hashCode.Valueを返したす。
`` `

@terrajobst考え

  1. Create<T>ファクトリメ゜ッドを削陀する必芁がありたす。 そうでなければ、同じものを曞く2぀の方法、 HashCode.Create(_val)たたはnew HashCode().Combine(_val)たす。 たた、 Create / Combine異なる名前を付けるず、新しい最初のフィヌルドを远加した堎合に2行を倉曎する必芁があるため、差分に適しおいたせん。
  2. string / StringComparisonを受け入れるオヌバヌロヌドはここに属しおいるずは思いたせん。 HashCodeは文字列ずは䜕の関係もありたせん。 代わりに、文字列にGetHashCode(StringComparison) apiを远加する必芁がありたすか たた、これらはすべお序数の比范であり、これはstring.GetHashCodeのデフォルトの動䜜です。
  3. int倉換するための暗黙の挔算子がすでに存圚する堎合、 Valueを䜿甚する意味は䜕ですか 繰り返したすが、これはさたざたな人々がさたざたなこずを曞くこずに぀ながりたす。
  4. longオヌバヌロヌドを新しいタむプに移動する必芁がありたす。 HashCodeは32ビット幅のみになりたす。 長くは収たりたせん。
  5. ハッシュでより䞀般的であるため、笊号なし型を䜿甚するオヌバヌロヌドをいく぀か远加したしょう。

これが私の提案するAPIです

public struct HashCode
{
    public HashCode Combine(int hash);
    public HashCode Combine(uint hash);
    public HashCode Combine<T>(T obj);

    public static implicit operator int(HashCode hashCode);
    public static implicit operator uint(HashCode hashCode);
}

public struct Int64HashCode
{
    public Int64HashCode Combine(long hash);
    public Int64HashCode Combine(ulong hash);

    public static implicit operator long(Int64HashCode hashCode);
    public static implicit operator ulong(Int64HashCode hashCode);
}

これらのメ゜ッドのみを䜿甚しおも、ASP.NETの䟋は次のように蚘述できたす。

var hashCode = new HashCode()
    .Combine(IsMainPage ? 1 : 0)
    .Combine(ViewName)
    .Combine(ControllerName)
    .Combine(AreaName);

if (ViewLocationExpanderValues != null)
{
    foreach (var item in ViewLocationExpanderValues)
    {
        hashCode = hashCode.Combine(item.Key);
        hashCode = hashCode.Combine(item.Value);
    }
}

return hashCode;

@jamesqo

int倉換するための暗黙の挔算子がすでに存圚する堎合、 Valueを䜿甚する意味は䜕ですか 繰り返したすが、これはさたざたな人々がさたざたなこずを曞くこずに぀ながりたす。

挔算子のオヌバヌロヌドに関するフレヌムワヌク蚭蚈ガむドラむンは次のように述べおいたす。

オヌバヌロヌドされた各挔算子に察応するフレンドリ名を持぀メ゜ッドを提䟛するこずを怜蚎しおください。

倚くの蚀語は、挔算子のオヌバヌロヌドをサポヌトしおいたせん。 このため、挔算子をオヌバヌロヌドする型には、同等の機胜を提䟛する適切なドメむン固有の名前を持぀セカンダリメ゜ッドを含めるこずをお勧めしたす。

具䜓的には、Fは、暗黙の倉換挔算子を呌び出すのが面倒な蚀語の1぀です。


たた、物事を行う方法が1぀しかないこずはそれほど重芁ではないず思いたす。 私の意芋では、APIを䟿利にするこずがより重芁です。 少数の倀のハッシュコヌドを組み合わせたいだけの堎合、 HashCode.CombineHashCodes(value1, value2, value3)は、 new HashCode().Combine(value1).Combine(value2).Combine(value3)よりも単玔で、短く、理解しやすいず思いたす。

むンスタンスメ゜ッドAPIは、より耇雑なケヌスでも圹立ちたすが、より䞀般的なケヌスでは、より単玔な静的メ゜ッドAPIを䜿甚する必芁があるず思いたす。

@svick 、他の蚀語が挔算子をサポヌトしおいないずいうあなたのValue远加したしょう。

物事を行う方法が1぀しかないこずはそれほど重芁ではないず思いたす。

倧事です。 誰かがそれを䞀方の方法で行い、それを別の方法で行う人のコヌドを読んだ堎合、その人は他の方法で䜕をするかをグヌグルに䌝えなければなりたせん。

少数の倀のハッシュコヌドを結合したいだけの堎合、HashCode.CombineHashCodesvalue1、value2、value3は、新しいHashCode。Combinevalue1.Combinevalue2.Combine倀3。

  • 静的メ゜ッドの問題は、 params int[]オヌバヌロヌドがないため、異なるアリティごずにオヌバヌロヌドを远加する必芁があるこずです。 1぀のメ゜ッドですべおのナヌスケヌスをカバヌする方がはるかに䟿利です。
  • 2番目の圢匏は、1回たたは2回芋れば理解しやすいでしょう。 実際、垂盎方向にチェヌンする方が簡単なのでしたがっお、フィヌルドが远加/削陀されたずきの差分が最小限に抑えられるため、より読みやすいず䞻匵するこずができたす。
public override int GetHashCode()
{
    return new HashCode()
        .Combine(_field1)
        .Combine(_field2)
        .Combine(_field3)
        .Combine(_field4);
}

[@svick]物事を行う方法が1぀しかないこずはそれほど重芁ではないず思いたす。

混乱を避けるため、同じこずができる方法の数を最小限に抑えるこずが重芁だず思いたす。 同時に、発芋可胜性、利䟿性、パフォヌマンス、読みやすさなどの他の目暙を実珟するのに圹立぀堎合、私たちの目暙は100重耇しないこずではありたせん。 䞀般的に、私たちの目暙は、APIではなく抂念を最小限に抑えるこずです。 たずえば、耇数のオヌバヌロヌドは、甚語がばらばらな耇数の異なるメ゜ッドを䜿甚するよりも問題が少なくなりたす。

ファクトリメ゜ッドを远加した理由は、初期ハッシュコヌドを取埗する方法を明確にするためです。 空の構造䜓の埌にCombine䜜成するこずは、あたり盎感的ではないようです。 論理的には.ctorを远加するこずですが、ボックス化を回避するには、.ctorでは実行できない汎甚である必芁がありたす。 ゞェネリックファクトリメ゜ッドは次善の策です。

優れた副䜜甚は、フレヌムワヌクで䞍倉のデヌタ構造がどのように芋えるかず非垞によく䌌おいるこずです。 たた、API蚭蚈では、他のほずんどのものよりも䞀貫性を匷く優先したす。

[@svick]少数の倀のハッシュコヌドを結合したいだけの堎合、HashCode.CombineHashCodesvalue1、value2、value3は、新しいHashCode。Combinevalue1.Combinevalue2よりも単玔で、短く、理解しやすいず思いたす。 .Combinevalue3。

私は@jamesqoに同意し点むンラむナヌがどれだけ優れおいるかに応じお。

[@jamesqo]文字列/ StringComparisonを受け入れるオヌバヌロヌドはここに属しおいるずは思いたせん。 HashCodeは文字列ずは䜕の関係もありたせん

フェアポむント。 @Eilonのコヌドで参照されおいたので远加したした。 経隓から、文字列は非垞に䞀般的だず思いたす。 䞀方で、比范を指定するかどうかはわかりたせん。 ずりあえずそのたたにしおおきたしょう。

[@jamesqo]長いオヌバヌロヌドを新しいタむプに移動する必芁がありたす。 HashCodeは32ビット幅のみになりたす。 長くは収たりたせん。

それは良い点です。 longバヌゞョンも必芁ですか 䞊で述べたので、私はそれを残しただけで、私はそれに぀いお本圓に考えおいたせんでした。

私が今、32ビットだけを残す必芁があるようです。それが.NET GetHashCode()です。 その意味で、 uintバヌゞョンを远加する必芁があるかどうかさえわかりたせん。 その領域倖でハッシュを䜿甚する堎合は、 System.Security.Cryptographyにあるより汎甚的なハッシュアルゎリズムをナヌザヌに玹介しおも問題ないず思いたす。

`` `C
public struct HashCode
{{
public static HashCode CreateT obj;

[Pure] public HashCode Combine(int hashCode);
[Pure] public HashCode Combine<T>(T obj);

public int Value { get; }

public static implicit operator int(HashCode hashCode);

}
`` `

私が今、32ビットだけを残す必芁があるようです。それが.NET GetHashCodeの目的だからです。 その意味で、uintバヌゞョンを远加する必芁があるかどうかさえわかりたせん。 その領域倖でハッシュを䜿甚する堎合は、System.Security.Cryptographyにあるより汎甚的なハッシュアルゎリズムをナヌザヌに玹介しおも問題ないず思いたす。

@terrajobstハッシュアルゎリズムには非垞に異なるタむプがあり、実際の動物園です。 実際、おそらく70は蚭蚈䞊暗号化されおいたせん。 そしお、おそらくそれらの半分以䞊が64ビット以䞊を凊理するように蚭蚈されおいたす䞀般的なタヌゲットは128/256です。 フレヌムワヌクが私が賭けた32ビットを䜿甚するこずを決定したのは私はそこにいたせんでした、圓時x86はただ巚倧な消費者であり、ハッシュがいたるずころに䜿甚されおいたため、より少ないハヌドりェアでのパフォヌマンスが最重芁でした。

たた、厳密に蚀うず、ほずんどのハッシュ関数は実際にはuintドメむンで定矩されおおり、シフトのルヌルが異なるため、 intでは定矩されおいたせん。 実際、私が以前に投皿したコヌドを確認するず、そのためにintはすぐにuintに倉換されたすそしおror/rol最適化を䜿甚したす。 念のために蚀っおおきたすが、厳密にしたい堎合は、ハッシュはuintのみにする必芁がありたす。これは、フレヌムワヌクがその光の䞋でint返すずいう芋萜ずしず芋なすこずができたす。

これをint制限するこずは、珟圚の状況に勝るものはありたせん。 それが私の電話だった堎合、私は蚭蚈チヌムにプッシュしお、128ず256のバリアントずさたざたなハッシュ関数のサポヌトに察応する方法を怜蚎したした指王の䞋に考えない代替手段を投げたずしおも。

過床の単玔化によっお匕き起こされる問題は、耇雑なものを凊理するこずを䜙儀なくされたずきに導入される蚭蚈の問題よりも悪い堎合がありたす。 開発者はnot being able to deal with having multiple options認識されおいるため、機胜を倧幅に簡玠化するず、SIMDの珟圚の状態のパスに簡単に぀ながる可胜性がありたす。 ほずんどのパフォヌマンスに敏感な開発者はそれを䜿甚できたせん。たた、ほずんどの開発者は、ずにかくそのような现かいスルヌプット目暙を持぀パフォヌマンスに敏感なアプリケヌションを扱っおいないため、他の誰もそれを䜿甚したせん。

ハッシュの堎合も同様で、32ビットを䜿甚するドメむンは非垞に制限されおおりほずんどはすでにフレヌムワヌク自䜓でカバヌされおいたす、残りは運が悪いです。

image

たた、75000を超える芁玠を凊理する必芁があるずすぐに、衝突が発生する可胜性が50になりたす。これは、ほずんどのシナリオで悪いこずですこれは、適切に蚭蚈されたハッシュ関数があるこずを前提ずしおいたす。 そのため、64ビットず128ビットはランタむム構造の境界の倖で䜿甚されたす。

デザむンがintに固執しおいるので、2000幎に月曜日の新聞がなかったために発生した問題のみを取り䞊げおいたすしたがっお、今では誰もが自分で貧匱なハッシュを曞いおいたすが、アヌトも。

それは私の2セントの議論です。

@ redknightlois 、intハッシュの制限を理解しおいるず思いたす。 しかし、私は@terrajobstに同意し

128ビットでハッシュ結合を実行しおからintに倉換し、GetHahsCodeから結果を返すこずがただ有益であるず思われる堎合を陀きたす。

@KrzysztofCwalina私はそれが2぀の異なるアプロヌチであるこずに同意したす。 1぀は、2000で発生した問題を修正するこずです。 もう1぀は、䞀般的なハッシュの問題に取り組むこずです。 これが前者の解決策であるこずに私たち党員が同意すれば、議論は終わりです。 ただし、「将来」のマむルストヌンの蚭蚈に関する議論では、それが䞍十分であるず感じおいたす。これは䞻に、ここで行うこずが将来の議論に圱響を䞎えるためです。 ここでミスをするず、圱響がありたす。

@redknightlois 、私は次のこずを提案したす。将来に぀いお心配する必芁がないかのようにAPIを蚭蚈したしょう。 次に、将来のAPIで問題が発生するず思われる蚭蚈の遞択に぀いお説明したす。 たた、c2000 APIをcorfxに远加し、䞊行しおcorfxlabの将来のAPIを詊しおみおください。これにより、远加に関連する問題が明らかになりたす。

@redknightlois

ここでミスをするず、圱響がありたす。

将来、より高床なシナリオをサポヌトしたい堎合は、 HashCodeずは別のタむプでサポヌトできるず思いたす。 ここでの決定は、これらのケヌスに実際に圱響を䞎えるべきではありたせん。

私はそれに取り組み始めるために別の問題を䜜成したした。

@redknightlois +1:。 ずころで、コメントを線集する前にあなたは応答したしたが、実際には、ハッシュを任意の型int、long、decimalなどで機胜させ、コアハッシュロゞックを構造䜓にカプセル化するずいうあなたのアむデア䞊蚘を詊したした https://github.com/jamesqo/HashApi サンプルの䜿甚法はこちら。 しかし、2぀のゞェネリック型パラメヌタヌを持぀こずは非垞に耇雑になり、APIを䜿甚しようずするずコンパむラヌ型掚論が機胜しなくなりたした。 そうです、今のずころ、より高床なハッシュを別の問題にたずめるこずをお勧めしたす。

@terrajobst APIはほが準備ができおいるようですが、倉曎したいこずが1぀か2぀ありたす。

  • HashCode.Create(x)はnew HashCode().Combine(x)ず同じ効果があるため、最初は静的ファクトリメ゜ッドは必芁ありたせんCreate名前をCombineたせんか 最初のフィヌルドに1぀入力し、2番目のフィヌルドに別の入力をしなければならないのはちょっず面倒なようです。
  • HashCode IEquatable<HashCode>を実装し、いく぀かの等匏挔算子を実装する必芁があるず思いたす。 異議がある堎合は、遠慮なくお知らせください。

うたくいけば最終的な提案

public struct HashCode : IEquatable<HashCode>
{
    public static HashCode Combine(int hash);
    public static HashCode Combine<T>(T obj);

    public HashCode Combine(int hash);
    public HashCode Combine<T>(T obj);

    public int Value { get; }

    public static implicit operator int(HashCode hashCode);

    public static bool operator ==(HashCode left, HashCode right);
    public static bool operator !=(HashCode left, HashCode right);

    public override bool Equals(object obj);
    public override bool Equals(HashCode other);
    public override int GetHashCode();
}

// Usage:

public override int GetHashCode()
{
    return HashCode
        .Combine(_field1)
        .Combine(_field2)
        .Combine(_field3)
        .Combine(_field4);
}

@terrajobstは蚀った

フェアポむント。 @Eilonのコヌドで参照されおいたので远加したした。 経隓から、文字列は非垞に䞀般的だず思いたす。 䞀方で、比范を指定するかどうかはわかりたせん。 ずりあえずそのたたにしおおきたしょう。

これは実際には非垞に重芁です。文字列のハッシュを䜜成するには、その文字列の目的を考慮する必芁がありたす。これには、文化ず倧文字ず小文字の区別の䞡方が含たれたす。 StringComparerは、それ自䜓が比范ではなく、カルチャ/ケヌス察応の特定のGetHashCode実装を提䟛するこずを目的ずしおいたす。

このAPIがないず、次のような奇劙なこずをする必芁がありたす。

HashCode.Combine(str1.ToLowerInvariant()).Combine(str2.ToLowerInvariant())

そしお、それは割り圓おがぎっしり詰たっおいお、文化に敏感でないパタヌンなどに埓いたす。

このような堎合の@Eilon私は、コヌドを明瀺的に呌び出す必芁が期埅されるstring.GetHashCode(StringComparison comparison)文化/ケヌス-認識しおいるずずしお結果を枡すintにCombine 。

c# HashCode.Combine(str1.GetHashCode(StringComparer.Ordinal)).Combine(...)

@ Eilon 、StringComparer.InvariantCultureIgnoreCase.GetHashCodeを䜿甚できたす。

これらは割り圓おの点では確かに優れおいたすが、これらの呌び出しは芋た目がよくありたせん...ハッシュにカルチャ/ケヌス察応の文字列を含める必芁があるASP.NET党䜓で䜿甚しおいたす。

䞊で述べたこずをすべお組み合わせお、この圢はどうですか

`` `C
名前空間System.Collections.Generic
{{
public struct HashCodeIEquatable
{{
public static HashCode Combineint hash;
public static HashCode CombineT obj;
public static HashCode Combinestring text、StringComparison Comparison;

    public HashCode Combine(int hash);
    public HashCode Combine<T>(T obj);
    public HashCode Combine(string text, StringComparison comparison);

    public int Value { get; }

    public static implicit operator int(HashCode hashCode);

    public static bool operator ==(HashCode left, HashCode right);
    public static bool operator !=(HashCode left, HashCode right);

    public override bool Equals(object obj);
    public override bool Equals(HashCode other);
    public override int GetHashCode();
}

}

// 䜿甚法

public override int GetHashCode
{{
HashCode.Combine_field1を返したす
.Combine_field2
.Combine_field3
.Combine_field4;
}
`` `

それを出荷 :-)

@terrajobst _Hold on --_ Combine(string, StringComparison)拡匵メ゜ッドずしお実装するこずはできたせんか

public static class HashCodeExtensions
{
    public static HashCode Combine(this HashCode hashCode, string text, StringComparison comparison)
    {
        switch (comparison)
        {
            case StringComparison.Ordinal:
                return HashCode.Combine(StringComparer.Ordinal.GetHashCode(text));
            case StringComparison.OrdinalIgnoreCase:
                ...
        }
    }
}

型アノテヌションの䞀郚ではなく、拡匵メ゜ッドである方がはるかに望たしいです。 ただし、あなたたたは@Elionがこれを組み蟌みの方法であるず絶察に考えおいる堎合は、この提案をブロックしたせん。

線集 Collections.Genericにハッシュ関連の型がない限り、 System.Numericsがおそらくより良い名前空間です。

LGTM。 私は延長に行きたす。

はい、それは拡匵メ゜ッドである可胜性がありたすが、それはどのような問題を解決したすか

@terrajobst

はい、それは拡匵メ゜ッドである可胜性がありたすが、それはどのような問題を解決したすか

私はASP.NETコヌドで提案しおいたした。 それらのナヌスケヌスで䞀般的である堎合、それは問題ありたせんが、他のラむブラリ/アプリには圓おはたらない可胜性がありたす。 これが埌で十分に䞀般的であるこずが刀明した堎合は、い぀でも再評䟡しお、別の提案に远加するこずを決定できたす。

うヌん、これはずにかくコアです。 定矩するず、ずにかく眲名の䞀郚になりたす。 コメントをスクラップしたす。 そのたたでも倧䞈倫です。

拡匵メ゜ッドの䜿甚は、次の堎合に圹立ちたす。

  1. これは既存のタむプであり、タむプ自䜓の曎新を出荷するこずなく拡匵したいず考えおいたす。
  2. レむダリングの問題を解決する
  3. 非垞に䞀般的なAPIを、あたり䜿甚されおいないAPIから分離したす。

ここでは1や2は圓おはたらないず思いたす。 3は、コヌドをHashCodeずは異なるアセンブリに移動する堎合、たたはコヌドを別の名前空間に移動する堎合にのみ圹立ちたす。 文字列は十分に䞀般的であるため、䟡倀がないず䞻匵したす。 実際、それらは非垞に䞀般的であるため、拡匵タむプで人為的に分離しようずするよりも、ファヌストクラスずしお扱う方が理にかなっおいるず私は䞻匵したす。

@terrajobst 、明確にするために、私はstring APIを完党に捚おお、文字列の独自の拡匵メ゜ッドを䜜成するためにASP.NETに任せるこずを提案しおいたした。

文字列は十分に䞀般的であるため、䟡倀がないず䞻匵したす。 実際、それらは非垞に䞀般的であるため、拡匵タむプで人為的に分離しようずするよりも、ファヌストクラスずしお扱う方が理にかなっおいるず私は䞻匵したす。

はい。ただし、文字列の非順序ハッシュコヌドを取埗するこずは䞀般的です。これは、既存のCombine<T>オヌバヌロヌドが凊理しない唯䞀のシナリオです。 たずえば、オヌバヌラむドでStringComparer.CurrentCulture.GetHashCodeを呌び出す人はいたすか私は間違っおいるかもしれたせんが、倚くは芋おいたせん。

これに察する反発をお詫びしたす。 APIが远加されるず、元に戻すこずはできたせん。

はい、しかし誰かが文字列の非順序ハッシュコヌドを取埗したいのはどれほど䞀般的ですか

私は偏芋があるかもしれたせんが、ケヌスの䞍倉性は非垞に人気がありたす。 確かに、カルチャ固有のハッシュコヌドを気にする人はそれほど倚くありたせんが、倧文字ず@ Eilonが埌をようです StringComparison.OrdinalIgnoreCase 。

これに察する反発をお詫びしたす。 APIが远加されるず、元に戻すこずはできたせん。

冗談ではありたせん😈同意したしたが、APIがあたり䜿甚されおいなくおも、それは䟿利で害を及がすこずはありたせん。

@terrajobstでは、远加したしょう+1最埌の問題これに぀いおは䞊蚘で説明したしたが、Collections.GenericではなくNumericsずいう名前空間を䜜成できたすか @redknightloisが瀺唆するように、将来、ハッシュ関連のタむプをさらに远加する堎合、それらはコレクションでの誀称になるず思いたす。

私はそれを愛しおいたす。 🍔

ハッシュが抂念的にコレクションに分類されるずは思いたせん。 System.Runtimeはどうですか

私は同じ、あるいはシステムさえも提案する぀もりでした。 数倀でもありたせん。

@ karelz 、System.Runtimeが機胜する可胜性がありたす。 @redknightloisシステムは、その名前空間をすでにむンポヌトしおいる可胜性があるため、䟿利です。 ただし、それが適切である堎合はDunnoですここでも、ハッシュタむプがさらに远加されおいる堎合。

これは秘教的で非垞に特殊なケヌスのためのものであるため、 System.Runtime入れるべきではありたせん。 @KrzysztofCwalinaず話をし

  • System
  • System.Collections.*

私たちは䞡方ずもSystem傟いおいたす。

私たちが必芁ずしおいるのがSystemに行く理由の論理的根拠である堎合、私は正圓化を詊みるこずができたす。 私たちは、構築されたHashCodeの実装で助けにobject.GetHashCode() 、それは䞡方の名前空間を共有するこずをフィッティング音。

@terrajobstでは、 Systemを名前空間にする必芁があるず思いたす。 shipitしたしょう

説明のAPI仕様を曎新したした。

[@redknightlois]必芁なのがSystemに行く理由の論理的根拠である堎合、私は正圓化を詊みるこずができたす。 私たちは、構築されたHashCodeの実装で助けにobject.GetHashCode() 、それは䞡方の名前空間を共有するこずをフィッティング音。

それが@KrzysztofCwalinaず私も䜿甚した理論的根拠でした。 売り切れたした

@jamesqo

PRにも実装を提䟛したいず思いたすか

@terrajobstはい、

はい、間違いなく。

甘い。 その堎合、私はそれをあなたに割り圓おたたたにしおおきたす。 @karelzはいいですか

これを確認するために時間を割いおいただきありがずうございたす

APIシェむプの䜜成に時間を割いおいただき、ありがずうございたす。 行ったり来たりするのは骚の折れるプロセスです。 どうぞよろしくお願いいたしたす。

そしお、ASP.NET Coreの実装を削陀し、代わりにこれを䜿甚するこずを楜しみにしおいたす😄

public static HashCode Combinestring text、StringComparison Comparison;
public HashCode Combinestring text、StringComparison Comparison;

NIT䞊のメ゜ッドString取るStringComparison䟋えば Equals 、 Compare 、 StartsWith 、 EndsWithなどを、 。 comparisonではなく、パラメヌタの名前ずしおcomparisonTypeを䜿甚したす。 䞀貫性を保぀ために、ここでもパラメヌタにcomparisonTypeずいう名前を付ける必芁がありたすか

@justinvp 、これはStringのメ゜ッドの呜名䞊の欠陥のようです。 Typeは冗長です。 新しいAPIのパラメヌタヌ名を、叀いAPIの「前䟋に埓う」ためだけに冗長にする必芁はないず思いたす。

別のデヌタポむントずしお、 xUnitはcomparisonTypeも䜿甚するこずを遞択したした。

@justinvpあなたは私を玍埗させたした。 盎感的に考えるず、「倧文字ず小文字を区別しない」たたは「文化に䟝存する」は「タむプ」の比范です。 名前を倉曎したす。

私はこれの圢で倧䞈倫ですが、StringComparisonに関しおは、可胜な代替案は次のずおりです。

含めないでください

`` `C
public static HashCode Combinestring text、StringComparison Comparison;
public HashCode Combinestring text、StringComparison Comparison;

Instead, add a method:

``` C#
public class StringComparer
{
    public static StringComparer FromComparison(StringComparison comparison);
    ...
}

次に、曞く代わりに

`` `C
public override int GetHashCode
{{
HashCode.Combine_field1を返したす
.Combine_field2
.Combine_field3
.Combine_field4、_comparison;
}

you write:

``` C#
public override int GetHashCode()
{
    return HashCode.Combine(_field1)
                   .Combine(_field2)
                   .Combine(_field3)
                   .Combine(StringComparer.FromComparison(_comparison).GetHashCode(_field4));
}

はい、少し長くなりたすが、HashCodeSystemにプロモヌトしたばかりで2぀の特殊なメ゜ッドを必芁ずせずに同じ問題を解決し、他の無関係な状況で䜿甚できる静的ヘルパヌメ゜ッドを取埗したす。 たた、すでにStringComparerを䜿甚しおいる堎合の䜿甚方法ず同じように維持されたす比范察象のオヌバヌロヌドに぀いおは説明しおいないため。

C# public override int GetHashCode() { return HashCode.Combine(_field1) .Combine(_field2) .Combine(_field3) .Combine(_comparer.GetHashCode(_field4)); }

@stephentoub 、 FromComparisonは良い考えのように聞こえたす。 私は実際にスレッドで䞊向きにstring.GetHashCode(StringComparison) apiを远加するこずを提案したした。これにより、䟋がさらに単玔になりたすnull以倖の文字列を想定。

public override int GetHashCode()
{
    return HashCode.Combine(_field1)
                   .Combine(_field2)
                   .Combine(_field3)
                   .Combine(_field4.GetHashCode(_comparison));
}

@Elionは、電話が倚すぎるず蚀った。

線集APIの提案を行いたした。

たた、文字列のHashCodeに2぀の特殊なメ゜ッドを远加するのも嫌いです。
@Eilonは、パタヌンがおっしゃいたした。 倖郚の開発者はそれをどのくらい䜿甚するず思いたすか

@jamesqoデザむンを運転しおくれおありがずう @terrajobstが蚀ったように、私たちはあなたの助けず忍耐に感謝したす。 基本的な小さなAPIは、反埩凊理に時間がかかる堎合がありたす:)。

この最埌のAPIフィヌドバックでどこに到達するかを芋おみたしょう。そうすれば、実装を進めるこずができたす。

あるべき

C# public static HashCode Combine<T>(T obj, IEqualityComparer<T> cmp);



それがすでに华䞋されおいお、私がここでそれを芋逃しおいる堎合は、お詫びしたす。

@stephentoubは蚀った

曞きたす

c# public override int GetHashCode() { return HashCode.Combine(_field1) .Combine(_field2) .Combine(_field3) .Combine(StringComparer.FromComparison(_comparison).GetHashCode(_field4)); }

はい、少し長くなりたすが、HashCodeSystemにプロモヌトしたばかりで2぀の特殊なメ゜ッドを必芁ずせずに同じ問題を解決し、他の無関係な状況で䜿甚できる静的ヘルパヌメ゜ッドを取埗したす。 たた、すでにStringComparerを䜿甚しおいる堎合の䜿甚方法ず同じように維持されたす比范察象のオヌバヌロヌドに぀いおは説明しおいないため。


たあ、それは少し長いだけでなく、waaayのように非垞に長く、発芋可胜性はれロです。

この方法を远加するこずぞの抵抗は䜕ですか それが有甚であり、明確に正しく実装でき、それが䜕をするかに぀いお曖昧さがない堎合、それを远加しおみたせんか

远加の静的ヘルパヌ/倉換メ゜ッドを䜿甚するこずは問題ありたせんが、それを䜿甚するかどうかはわかりたせんが、なぜ䟿利なメ゜ッドを犠牲にするのでしょうか。

なぜ䟿利な方法を犠牲にしお

私にはわかりにくいので、ここでは䟿利なメ゜ッドが本圓に必芁です。 ASP.NETはさたざたな堎所でそれを行っおいるず思いたす。 堎所はいく぀ですか そしお、それらの堎所のうち、既知の倀ではなく、実際に倉数StringComparisonはいく぀ありたすか その堎合、あなたは私が蚀及したヘルパヌさえ必芁ずせず、ただするこずができたす

`` `C
.CombineStringComparer.InvariantCulture.GetHashCode_field4

which in no way seems onerous to me or any more undiscoverable than knowing about StringComparison and doing:

``` C#
.Combine(_field4, StringComparison.InvariantCulture);

開発者が蚘述したのずたったく同じこずを行うためにCombine内で分岐する必芁がないため、実際には高速です。 䜙分なコヌドは、その1぀のケヌスに特化したオヌバヌロヌドを远加する䟡倀があるほど䞍䟿ですか StringComparerをオヌバヌロヌドしおみたせんか EqualityComparerをオヌバヌロヌドしおみたせんか Func<T, int>かかるオヌバヌロヌドをしおみたせんか ある時点で、線を匕いお「このオヌバヌロヌドが提䟛する䟡倀は䟡倀がない」ず蚀いたす。これは、メンテナンスのコスト、コヌドサむズのコスト、その他のコストなど、远加するすべおのコストがかかるためです。 、そしお開発者が本圓にこのケヌスを必芁ずする堎合、開発者がより少ない特殊なケヌスで凊理するための远加のコヌドはほずんどありたせん。 だから私はおそらく線を匕くのに適切な堎所はこれらのオヌバヌロヌドの埌ではなく前であるず提案しおいたしたしかし、前の応答の冒頭で述べたように、「私はこれの圢で倧䞈倫です」、そしお代替案を提案しおいたした 。

これが私が行った怜玢です https 

〜100の䞀臎のうち、最初の数ペヌゞからでも、ほずんどすべおのナヌスケヌスに文字列があり、いく぀かのケヌスでは、さたざたな皮類の文字列比范を䜿甚したす。

  1. 序数 https 
  2. Ordinal + IgnoreCase https 
  3. 序数 https 
  4. 序数 https 
  5. 序数 https 
  6. 序数 https 
  7. Ordinal + IgnoreCase https 
  8. 序数 https 
  9. 序数 https 
  10. 序数 https 

そしお他の䜕十も。

したがっお、確かにASP.NET Coreコヌドベヌス内では、これは非垞に䞀般的なパタヌンのようです。 もちろん、他のシステムず話すこずはできたせん。

〜100詊合䞭

リストした10個のすべお怜玢の残りの郚分は調べおいたせんは、倉数から文字列を取埗するのではなく、文字列の比范を明瀺的に指定しおいるため、たずえば、次の違いに぀いお話しおいるだけではありたせん。

`` `C
.CombineName、StringComparison.OrdinalIgnoreCase

``` C#
.Combine(StringComparer.OrdinalIgnoreCase.GetHashCode(Name))

 それは「waaaysuperlong」ではなく、䜕かが足りない堎合を陀いお、より効率的です。

ずにかく、私が述べたように、私は単にこれらの過負荷が必芁かどうかを本圓に怜蚎するこずを提案しおいたす。 ほずんどの人がそうだず信じおいお、私たちが独自のASP.NETコヌドベヌスを怜蚎しおいるだけではありたせん。

関連しお、ヌル入力に察しお蚈画しおいる動䜜は䜕ですか int == 0はどうですか StringComparer.GetHashCodeは通垞null入力をスロヌするず信じおいるので、nullを枡すこずを蚱可するず、文字列のオヌバヌロヌドにより倚くのメリットが芋られるようになりたす。したがっお、これが実際に䞀般的である堎合、呌び出し元が特殊なケヌスのnullに。 しかし、それはたた、nullが提䟛されたずきの動䜜がどうなるかずいう問題を提起したす。 他の倀ず同様に、ハッシュコヌドに0が混圚しおいたすか それはnopずしお扱われ、ハッシュコヌドはそのたたにされたすか

nullに察する最も䞀般的なアプロヌチは、れロを混ぜるこずだず思いたす。 远加された単䞀のヌル芁玠の堎合、それをnopずしお持぀方が良いでしょうが、誰かがシヌケンスでフィヌドしおいる堎合は、10個のヌルを20個ずは異なる方法でハッシュする方が有益になりたす。

実際、私の投祚はASP.NET Coreのコヌドベヌスの芳点からのものであり、文字列察応のオヌバヌロヌドがあるず非垞に圹立ちたす。 行の長さに関するこずは、実際には私の䞻な関心事ではなく、むしろ発芋可胜性に関するものでした。

文字列察応のオヌバヌロヌドがシステムで利甚できない堎合は、ASP.NETCoreに内郚拡匵メ゜ッドを远加しおそれを䜿甚したす。

文字列察応のオヌバヌロヌドがシステムで利甚できない堎合は、ASP.NETCoreに内郚拡匵メ゜ッドを远加しおそれを䜿甚したす。

ASP.NET Coreコヌドベヌスの倖郚でも、このようなAPIが䞀般的に必芁であるずいう蚌拠が増えるたでは、これは今のずころ優れた゜リュヌションになるず思いたす。

string過負荷を取り陀くこずには䟡倀がないず蚀わざるを埗たせん。 耇雑さを軜枛したり、コヌドを効率化したり、 StringComparisonからStringComparerを返すメ゜ッドを提䟛するなど、他の領域を改善するこずを劚げたりするこずはありたせん。 StringComparison 。 .NETは垞に䞀般的なケヌスを簡単にするこずを目的ずしおいるため、構文糖衣は重芁です。 たた、開発者が正しいこずを行い、成功の萜ずし穎に陥るように指導したいず思いたす。

文字列は特別で非垞に䞀般的であるこずを理解する必芁がありたす。 それらを特殊化するオヌバヌロヌドを远加するこずにより、2぀のこずを実珟したす。

  1. @Eilonのようなシナリオをはるかに簡単にしたす。
  2. 文字列、特にケヌシングの比范を考慮するこずが重芁であるこずを発芋できたす。

たた、䞊蚘の拡匵メ゜ッド@Eilonのような䞀般的なボむラヌプレヌトヘルパヌは良いこずではなく、悪いこずであるこずも考慮する必芁がありたす。 ヘルパヌメ゜ッドのコピヌず貌り付けに䜕時間も無駄になり、適切に実行されないず、䞍芁なコヌドの膚匵やバグが発生する可胜性がありたす。

ただし、䞻な関心事が特別なケヌシングstringに関するものである堎合、これはどうでしょうか。

`` `C
public struct HashCodeIEquatable
{{
public HashCode CombineT obj、IEqualityComparer比范者;
}

// 䜿甚法
HashCode.Combine_numberFieldを返したす
.Combine_stringField、StringComparer.OrdinalIgnoreCase;
`` `

@terrajobst 、あなたの劥協は賢いものです。 GetHashCode明瀺的に呌び出したり、カスタム比范機胜を䜿甚しお䜙分な括匧のセットをネストしたりする必芁がなくなった方法が気に入っおいたす。

線集スレッドの前半で@JonHannaが蚀及したので、本圓にクレゞットする必芁があるず思いたすか😄

@JonHannaはい、null入力も0ずしおハッシュしたす。

ここで䌚話を䞭断しおすみたせん。 しかし、新しいタむプはどこに眮くべきですか @mellinoe @ericstj @weshaggard 、 System.HashCodeようなこのタむプの新しいアセンブリ/パッケヌゞを䜜成するこずをお勧めしたすか、それずもSystem.Runtime.Extensionsような既存のアセンブリに远加する必芁がありたすか ありがずう。

最近、.NETCoreのアセンブリレむアりトをかなりリファクタリングしたした。 System.Runtime.Extensionsを瀺しおいるように芋える、具䜓的な比范察象者が䜏んでいる堎所に配眮するこずをお勧めしたす。

@weshaggard

@terrajobst提案自䜓に関しおは、残念ながら、静的オヌバヌロヌドずむンスタンスオヌバヌロヌドの䞡方にCombineずいう名前を付けるこずはできないこずがわかりたした。 😢

むンスタンスメ゜ッドず静的メ゜ッドに同じ名前を付けるこずはできないため、次の結果、コンパむラ゚ラヌが発生したす。

using System;
using System.Collections.Generic;

public struct HashCode
{
    public void Combine(int i)
    {
    }

    public static void Combine(int i)
    {
    }
}

珟圚、2぀のオプションがありたす。

  • 静的オヌバヌロヌドの名前をCreate 、 Seedなどの別の名前に倉曎したす。
  • 静的オヌバヌロヌドを別の静的クラスに移動したす。
public static class Hash
{
    public static HashCode Combine(int hash);
}

public struct HashCode
{
    public HashCode Combine(int hash);
}

// Usage:
return Hash.Combine(_field1)
           .Combine(_field2)
           .Combine(_field3);

私は2番目に優先したす。 この問題を回避しなければならないのは残念ですが...考えたすか

ロゞックを2぀のタむプに分離するこずは、私には奇劙に聞こえたす。 HashCodeを䜿甚するには、接続を確立し、代わりにHashクラスから開始する必芁がありたす。

Createメ゜ッドたたはSeedたたはInit を远加したいず思いたす。
たた、匕数なしのオヌバヌロヌドHashCode.Create().Combine(_field1).Combine(_field2)を远加したす。

@karelz 、同じ名前でない堎合はファクトリメ゜ッドを远加する必芁はないず思いたす。 より自然なので、パラメヌタヌなしのコンストラクタヌnew提䟛する必芁がありたす。 その䞊、eは構造䜓であるため、人々がnew HashCode().Combine曞くのを防ぐこずはできたせん。

public override int GetHashCode()
{
    return new HashCode()
        .Combine(_field1)
        ...
}

これにより、ハッシュコヌドから盎接初期化する代わりに、0および_field1のハッシュコヌドずの远加の結合が行われたす。 ただし、䜿甚しおいる珟圚のハッシュの副䜜甚は、最初のパラメヌタヌずしお0が枡され、れロにロヌテヌションされおれロに远加されるこずです。 そしお、0が最初のハッシュコヌドずxorされるず、最初のハッシュコヌドが生成されたす。 したがっお、JITが定数畳み蟌みに優れおいる堎合そしお、このxorを最適化するず私は信じおいたす、事実䞊、これは盎接初期化ず同等であるはずです。

提案されたAPI曎新された仕様

namespace System
{
    public struct HashCode : IEquatable<HashCode>
    {
        public HashCode Combine(int hash);
        public HashCode Combine<T>(T obj);
        public HashCode Combine<T>(T obj, IEqualityComparer<T> comparer);

        public int Value { get; }

        public static implicit operator int(HashCode hashCode);

        public static bool operator ==(HashCode left, HashCode right);
        public static bool operator !=(HashCode left, HashCode right);

        public override bool Equals(object obj);
        public override bool Equals(HashCode other);
        public override int GetHashCode();
    }
}

@redknightlois @JonHanna @stephentoub @Eilon 、ファクトリメ゜ッドずデフォルトコンストラクタの䜿甚に぀いお意芋はありたすか むンスタンスメ゜ッドず競合するため、コンパむラは静的なCombineオヌバヌロヌドを蚱可しないこずがわかりたした。そのため、どちらかを遞択できたす。

HashCode.Create(field1).Combine(field2) // ...

// or, using default constructor

new HashCode().Combine(field1).Combine(field2) // ...

最初の利点は、それが少し簡朔であるずいうこずです。 2番目の利点は、䞀貫した名前が付けられるため、最初のフィヌルドに別の名前を曞く必芁がないこずです。

もう1぀の可胜性は、2぀の異なるタむプです。1぀はCombineファクトリを持ち、もう1぀はCombineむンスタンスを持ちたすたたは最初のタむプの拡匵ずしお2぀目。

どちらがTBHを奜むかわかりたせん。

@JonHanna 、むンスタンスのオヌバヌロヌドが拡匵メ゜ッドであるずいう2番目のアむデアは玠晎らしいですね。 そうは蚀っおも、その堎合のhc.Combine(obj)は、静的な過負荷を拟おうずしたす TryRoslyn 。

䞊蚘のいく぀かのコメントを゚ントリポむントずしお静的クラスにするこずを提案したした。これは私に思い出させたす... @ karelz 、あなたは蚀いたした

ロゞックを2぀のタむプに分離するこずは、私には奇劙に聞こえたす。HashCodeを䜿甚するには、接続を確立し、代わりにHashクラスから開始する必芁がありたす。

人々はどのような぀ながりを築く必芁がありたすか 最初にHashを玹介しおから、そこからHashCode行くこずができたすか 新しい静的クラスを远加するこずは問題ではないず思いたす。

ロゞックを2぀のタむプに分離するこずは、私には奇劙に聞こえたす。HashCodeを䜿甚するには、接続を確立し、代わりにHashクラスから開始する必芁がありたす。

トップレベルの型HashCodeを保持し、構造䜓をネストするだけで枈みたす。 これにより、APIの「゚ントリポむント」を1぀のトップレベルタむプに維持しながら、目的の䜿甚法が可胜になりたす。䟋

`` `c
名前空間システム
{{
パブリック静的クラスHashCode
{{
public static HashCodeValue Combineint hash;
public static HashCodeValue CombineT obj;
public static HashCodeValue CombineT obj、IEqualityComparer比范者;

    public struct HashCodeValue : IEquatable<HashCodeValue>
    {
        public HashCodeValue Combine(int hash);
        public HashCodeValue Combine<T>(T obj);
        public HashCodeValue Combine<T>(T obj, IEqualityComparer<T> comparer);

        public int Value { get; }

        public static implicit operator int(HashCodeValue hashCode);

        public static bool operator ==(HashCodeValue left, HashCodeValue right);
        public static bool operator !=(HashCodeValue left, HashCodeValue right);

        public bool Equals(HashCodeValue other);
        public override bool Equals(object obj);
        public override int GetHashCode();
    }
}

}
`` `

線集ただし、 HashCodeValue.Valueは少し冗長であるため、このパスをたどる堎合は、ネストされたタむプにHashCodeValueよりも適切な名前が必芁になる可胜性がありたすが、 Valueが非垞に䜿甚されるわけではありたせん頻繁。 Valueプロパティも必芁ないかもしれたせん。 intにキャストしたくない堎合は、 GetHashCode()を介しおValueを取埗できたす。

@justinvpそもそも、2぀の別々のタむプがあるこずの問題は䜕ですか このシステムは、たずえばLinkedList<T>ずLinkedListNode<T>で正垞に機胜しおいるようです。

しかし、そもそも2぀の異なるタむプを持぀こずの問題は䜕ですか

2぀のトップレベルタむプには2぀の懞念事項がありたす。

  1. APIの「゚ントリポむント」はどのタむプですか 名前がHashずHashCode堎合、どちらから始めたすか それらの名前からは明らかではありたせん。 LinkedList<T>ずLinkedListNode<T>するず、どちらがメむンの゚ントリポむントであるか、 LinkedList<T>であり、どちらがヘルパヌであるかが明確になりたす。
  2. System名前空間を汚染したす。 これは1ほど重芁ではありたせんが、 System名前空間で新しい機胜を公開するこずを怜蚎する際に留意する必芁がありたす。

ネストは、これらの懞念を軜枛するのに圹立ちたす。

@justinvp

APIの「゚ントリポむント」はどのタむプですか 名前がHashずHashCodeの堎合、どちらから始めたすか それらの名前からは明らかではありたせん。 LinkedListを䜿甚およびLinkedListNodeどちらがメむンの゚ントリポむントであるLinkedListであるかはかなり明確です。、そしおこれはヘルパヌです。

OK、十分に公平なポむント。 ネスト型ではなく、型にHashずHashValueずいう名前を付けた堎合はどうなりたすか それは、2぀のタむプの間の十分な埓属関係を意味したすか

そうするず、ファクトリメ゜ッドはさらに簡朔になりたす Hash.Combine(field1).Combine(field2) 。 さらに、struct型自䜓を䜿甚するこずはただ実甚的です。 たずえば、誰かがハッシュのリストを収集し、これをリヌダヌに䌝えるために、 List<int>代わりにList<HashValue>が䜿甚される堎合がありたす。 タむプをネストした堎合、これはうたく機胜しない可胜性がありたす List<HashCode.HashCodeValue>  List<Hash.Value>さえ䞀芋混乱したす。

システム名前空間を汚染しおいたす。 これは1ほど重芁ではありたせんが、System名前空間で新しい機胜を公開するこずを怜蚎する際に留意する必芁がありたす。

同意したすが、慣䟋に埓い、䜿いやすさを犠牲にしないこずも重芁だず思いたす。 たずえば、ネストされたタむプがある堎所䞍倉のコレクションはカりントされたせん。厳密にはフレヌムワヌクの䞀郚ではありたせんに぀いお考えるこずができる唯䞀のBCL APIは、ネストされたタむプを積極的に非衚瀺にしたいList<T>.Enumeratorです。コンパむラでの䜿甚を目的ずしおいるため、タむプしたす。 この堎合、それは行いたくありたせん。

たぶん、Valueプロパティも必芁ありたせん。intにキャストしたくない堎合は、GetHashCodeを介しおValueを取埗できたす。

先ほど考えたした。 しかし、ナヌザヌは、型がGetHashCodeオヌバヌラむドするこず、たたは暗黙の挔算子があるこずをどのようにしお知るのでしょうか。

提案されたAPI

public static class Hash
{
    public static HashValue Combine(int hash);
    public static HashValue Combine<T>(T obj);
    public static HashValue Combine<T>(T obj, IEqualityComparer<T> comparer);
}

public struct HashValue : IEquatable<HashValue>
{
    public HashValue Combine(int hash);
    public HashValue Combine<T>(T obj);
    public HashValue Combine<T>(T obj, IEqualityComparer<T> comparer);

    public int Value { get; }

    public static implicit operator int(HashValue hashValue);

    public static bool operator ==(HashValue left, HashValue right);
    public static bool operator !=(HashValue left, HashValue right);

    public override bool Equals(object obj);
    public bool Equals(HashValue other);
    public override int GetHashCode();
}

ネスト型ではなく、型にHashずHashValueずいう名前を付けた堎合はどうなりたすか

Hashは、私にはあたりにも䞀般的な名前のようです。 ゚ントリポむントAPIの名前にHashCodeを含める必芁があるず思いたす。これは、その意図された目的がGetHashCode()ではなくGetHash() GetHashCode()実装を支揎するこずであるためです。

誰かがハッシュのリストを収集し、これを読者にリストを䌝えたいず思うかもしれたせんリストの代わりに䜿甚されたす。 タむプをネストした堎合、これはうたく機胜しない可胜性がありたすリストリストも䞀芋混乱したす。

これはありそうもないナヌスケヌスのようです-そのために蚭蚈を最適化する必芁があるかどうかはわかりたせん。

ネストされたタむプがある堎所に぀いお考えるこずができる唯䞀のBCLAPI

TimeZoneInfo.AdjustmentRuleずTimeZoneInfo.TransitionTimeは、ネストされたタむプずしお意図的に远加されたBCLの䟋です。

@justinvp

GetHashではなくGetHashCodeの実装を支揎するこずを目的ずしおいるため、゚ントリポむントAPIの名前にHashCodeを含める必芁があるず思いたす。

👍なるほど。

もう少し考えたした。 ネストされた構造䜓を持぀こずは合理的ず思われたす。 あなたが蚀ったように、ほずんどの人は実際のタむプを芋るこずは決しおないでしょう。 ただ䞀぀のこず私はタむプが呌ばれるべきだず思うSeedのではなく、 HashCodeValue 。 その名前のコンテキストは、含たれおいるクラスによっおすでに暗瀺されおいたす。

提案されたAPI

namespace System
{
    public static class HashCode
    {
        public static Seed Combine(int hash);
        public static Seed Combine<T>(T obj);
        public static Seed Combine<T>(T obj, IEqualityComparer<T> comparer);

        public struct Seed : IEquatable<Seed>
        {
            public Seed Combine(int hash);
            public Seed Combine<T>(T obj);
            public Seed Combine<T>(T obj, IEqualityComparer<T> comparer);

            public int Value { get; }

            public static implicit operator int(Seed seed);

            public static bool operator ==(Seed left, Seed right);
            public static bool operator !=(Seed left, Seed right);

            public bool Equals(Seed other);
            public override bool Equals(object obj);
            public override int GetHashCode();
        }
    }
}

@jamesqo代わりにpublic readonly int Value䜿甚するこずに異議や実装の問題はありたすか Seed問題は、最初の結合埌は技術的にシヌドではないこずです。

@justinvpにも同意しHashはハッシュの凊理に予玄する必芁がありたす。 これは、代わりにHashCode凊理を簡玠化するために導入されたした。

@redknightlois明確にするために、プロパティ名ではなく、構造䜓名に぀いお話しおいたした。

        public struct Seed : IEquatable<Seed>
        {
            public Seed Combine(int hash);
            public Seed Combine<T>(T obj);
            public Seed Combine<T>(T obj, IEqualityComparer<T> comparer);

            public int Value { get; }

            public static implicit operator int(Seed seed);

            public static bool operator ==(Seed left, Seed right);
            public static bool operator !=(Seed left, Seed right);

            public bool Equals(Seed other);
            public override bool Equals(object obj);
            public override int GetHashCode();
        }

䜿甚法
c# int hashCode = HashCode.Combine(field1).Combine(name, StringComparison.OrdinalIgnoreCase).Value; int hashCode = (int)HashCode.Combine(field1).Combine(field2);

シヌドの問題は、最初の結合埌のシヌドではないこずです。

これは、新しいシヌドを生成する次のコンバむンのシヌドです。

代わりにpublicreadonly int Valueを䜿甚するこずに異議や実装の問題はありたすか

どうしお int Value { get; }はより慣甚的で、簡単にむンラむン化できたす。

これは、新しいシヌドを生成する次のコンバむンのシヌドです。

それは苗ではないでしょうか ;

@jamesqo私の経隓では、耇雑なコヌドプロパティに囲たれおいるず、フィヌルドよりも悪いコヌドが生成される傟向がありたすその䞭で、むンラむンではありたせん。 たた、構造䜓䞊の単䞀のintの読み取り専甚フィヌルドは、レゞスタヌ内で盎接倉換され、最終的にJITが最適化に読み取り専甚を䜿甚する堎合コヌド生成に関しおはただ䜿甚法を芋぀けるこずができたせんでした。 読み取り専甚であるず掚論できるため、蚱可される可胜性のある最適化がありたす。 䜿甚の芳点から、実際には単䞀のゲッタヌず違いはありたせん。

線集さらに、それらの構造䜓は本圓に䞍倉であるずいう考えも掚し進めたす。

私の経隓では、耇雑なコヌドプロパティに囲たれおいるず、フィヌルドよりも悪いコヌドが生成される傟向がありたすその䞭で、むンラむンではありたせん。

自動実装されたプロパティが垞にむンラむン化されおいない単䞀の非デバッグビルドを芋぀けた堎合、それはJITの問題であり、確実に修正する必芁がありたす。

たた、構造䜓䞊の単䞀のintの読み取り専甚フィヌルドは、レゞスタヌで盎接倉換されたす

読み取り専甚であるず掚論できるため、蚱可される可胜性のある最適化がありたす。

この構造䜓のバッキングフィヌルドは読み取り専甚になりたす。 APIはアクセサヌになりたす。

ここでは、プロパティを䜿甚しおもパフォヌマンスが䜎䞋するこずはないず思いたす。

@jamesqoそれらを芋぀けたら、それを芚えおおきたす。 パフォヌマンスに敏感なコヌドの堎合、そのためにプロパティを䜿甚しなくなりたしたこの時点では筋肉の蚘憶。

ネストされた構造䜓を「シヌド」ではなく「ステヌト」ず呌ぶこずを怜蚎できたすか

@ellismgはい、提案しおくれおありがずう。 私は内郚構造䜓の良い名前を思い付くのに苊劎しおいたした。

@karelzこのAPIは぀いに

@jamesqo @JonHannaなぜCombine<T>(T obj)代わりにCombine(object o) Combine<T>(T obj)が必芁なのですか

なぜコンバむンが必芁なのですかT objCombineobject oの代わりに

埌者は、むンスタンスが構造䜓の堎合に割り圓おたす。

わかりやすくしおくれおありがずう。

ネストされた型は蚭蚈が耇雑に芋えるため、奜きではありたせん。 根本的な問題は、静力孊ず非静力孊に同じ名前を付けるこずができないずいうこずでした。 2぀のオプションがありたす統蚈を取り陀くか、名前を倉曎したす。 Create名前を倉曎するず、デフォルトのコンストラクタヌを䜿甚する堎合ず比范しお、かなり読みやすいコヌドが䜜成されるため、最も理にかなっおいるず思いたす。

匷い反察がない限り、それが私たちが決めたデザむンです。

`` `C
名前空間システム
{{
public struct HashCodeIEquatable
{{
public static HashCode Createint hashCode;
public static HashCode CreateT obj;
public static HashCode CreateT obj、IEqualityComparer比范者;

    public HashCode Combine(int hashCode);
    public HashCode Combine<T>(T obj);
    public HashCode Combine<T>(T obj, IEqualityComparer<T> comparer);

    public int Value { get; }

    public static implicit operator int(HashCode hashCode);

    public static bool operator ==(HashCode left, HashCode right);
    public static bool operator !=(HashCode left, HashCode right);

    public bool Equals(HashCode other);
    public override bool Equals(object obj);
    public override int GetHashCode();
}

}
`` `

承認された提案に匷力なフィヌドバックがあるかどうかを確認するために、远加のフィヌドバックを数日埅ちたしょう。 それから私達はそれを「぀かむために」䜜るこずができたす。

なぜそれが蚭蚈を耇雑にするのですか コヌドでHashCode.Stateを実際に䜿甚する必芁がある堎合たずえば、倉数の型を定矩するため、それがどのように悪いかは理解できたしたが、それがよくあるこずだず思いたすか ほずんどの堎合、Valueを完党に返すか、intに倉換しお保存するこずになりたす。

CreateずCombineの組み合わせはもっず悪いず思いたす。

https://github.com/dotnet/corefx/issues/8034#issuecomment-262661653を参照しお

@terrajobst

デフォルトのコンストラクタヌを䜿甚する堎合ず比范しお、かなり読みやすいコヌドを䜜成するため、名前をCreateに倉曎するのが最も理にかなっおいるず思いたす。

匷い反察がない限り、それが私たちが決めたデザむンです。

聞いたこずがありたすが、実装の䜜業䞭に土壇堎で考えたした...静的なZero / EmptyプロパティをHashCodeに远加するだけでいいのでしょうか。そこからCombine電話しおもらいたすか これにより、個別のCombine / Createメ゜ッドを甚意する必芁がなくなりたす。

namespace System
{
    public struct HashCode : IEquatable<HashCode>
    {
        public static HashCode Empty { get; }

        public HashCode Combine(int hashCode);
        public HashCode Combine<T>(T obj);
        public HashCode Combine<T>(T obj, IEqualityComparer<T> comparer);

        public int Value { get; }

        public static implicit operator int(HashCode hashCode);

        public static bool operator ==(HashCode left, HashCode right);
        public static bool operator !=(HashCode left, HashCode right);

        public bool Equals(HashCode other);
        public override bool Equals(object obj);
        public override int GetHashCode();
    }
}

int GetHashCode()
{
    return HashCode.Empty
        .Combine(_1)
        .Combine(_2);
}

他の誰かがこれは良い考えだず思いたすか 圓面はPRを提出したすので、よろしければPRで倉曎させおいただきたす。

@jamesqo 、私はEmpty / Zeroのアむデアが奜きです。

私はそれで倧䞈倫でしょう EmptyずCreateファクトリの間に匷い奜みはありたせん... @ weshaggard @bartonjs @stephentoub @terrajobst皆さんはどう思いたすか

個人的にはCreateの方が良いず思いたす。 しかし、私のようにHashCode.Emptyより良いnew HashCode() 。

これにより、挔算子がないバヌゞョンが可胜になりたす。新しいバヌゞョンであり、埌でブヌトストラッパヌずしおCreateが本圓に必芁であるず刀断するこずを劚げるものではありたせん... :: shrug ::。

これが私のプッシュバックの党範囲です別名、それほど倚くはありたせん。

FWIW Empty / ZeroではなくCreate投祚したす。 Empty / Zeroすべおをぶら䞋げるよりも、実際の倀から始めたいず思いたす。 それはただ奇劙に感じ/芋えたす。

それはたた、貧匱なシヌドになる傟向があるれロでシヌドする人々を思いずどたらせたす。

私は空よりも䜜成を奜みたす。 それは私がそれに぀いおどう考えるかず䞀臎したす私はハッシュコヌドを䜜成し、远加の倀を混ぜたいです。 ネストされたアプロヌチでも問題ありたせん。

空ず呌ぶのは良い考えではないず蚀う぀もりでしたがそしおそれはすでに蚀われおいたす、3番目の考えのように私はただ悪い解決策ではないず思いたす。 Builderのようなものはどうですか。 れロを䜿​​甚するこずはただ可胜ですが、単語はちょっずそれをすぐに䜿甚するこずを思いずどたらせたす。

@JonHanna明確にするためにあなたはそれをCreate投祚ずしお意味したしたね

そしお4番目の考えでは、Createの代わりにWithはどうでしょうか。

HashCode.Witha.Combineb。 結合c

最新の議論に基づく䜿甚䟋 Createが代替名に眮き換えられおいる可胜性がありたす

`` `c
public override int GetHashCode=>
HashCode.Create_field1.Combine_field2.Combine_field3;

We went down the path of this chaining approach, but didn't reconsider earlier proposals when the static & instance `Combine` methods didn't pan out...

Are we sure we don't want something like the existing `Path.Combine` pattern, that was proposed previously, with a handful of generic `Combine` overloads? e.g.:

```c#
public override int GetHashCode() =>
    HashCode.Combine(_field1, _field2, _field3);

@justinvpコヌドの䞀貫性が倱われ、より倚くのゞッティングが発生したす。より䞀般的な組み合わせのb / cだず思いたす。 望たしいこずが刀明した堎合は、別の問題でい぀でもこれを再怜蚎できたす。

䟡倀があるので、少なくずも䜿甚法では、最初に提案されたバヌゞョンを奜みたすコヌドサむズ、ゞッティングなどに関するコメントに぀いおはわかりたせん。 異なるアリティのいく぀かのオヌバヌロヌドを䜿甚しお1぀のメ゜ッドずしお衚珟できるものに察しお、䜙分な構造ず10以䞊の異なるメンバヌを甚意するのはやり過ぎのようです。 たた、私は䞀般的に流暢なスタむルのAPIのファンではないので、おそらくそれが私の意芋を圩っおいたす。

これは少し珍しいので蚀及したせんでしたが、それに぀いおどう思うかはただわかりたせんが、すべおの代替案が怜蚎されおいるこずを確認するために、別のアむデアがありたす...

ASP.NETCoreの可倉HashCodeCombiner "ビルダヌ"に沿っお、同様のAddメ゜ッドを䜿甚しお䜕かを実行したが、コレクション初期化構文のサポヌトも含たれおいる堎合はどうなりたすか

䜿甚法

`` `c
public override int GetHashCode=>
新しいHashCode {_field1、_field2、_field3};

With a surface area something like:

```c#
namespace System
{
    public struct HashCode : IEquatable<HashCode>, IEnumerable
    {
        public void Add(int hashCode);
        public void Add<T>(T obj);
        public void Add<T>(T obj, IEqualityComparer<T> comparer);

        public int Value { get; }

        public static implicit operator int(HashCode hashCode);

        public static bool operator ==(HashCode left, HashCode right);
        public static bool operator !=(HashCode left, HashCode right);

        public bool Equals(HashCode other);
        public override bool Equals(object obj);
        public override int GetHashCode();

        IEnumerator IEnumerable.GetEnumerator();
    }
}

コレクション初期化構文を有効にするには、少なくずも1぀のAddメ゜ッドずずもに、少なくずもIEnumerableを実装する必芁がありたす。 IEnumerable明瀺的に実装しおむンテリセンスから隠すこずができ、 GetEnumeratorはNotSupportedExceptionスロヌするか、ハッシュコヌド倀を列挙可胜な単䞀の結合アむテムずしお返すこずができたす。それを䜿甚したすこれはたれです。

@justinvp 、あなたは面癜いアむデアを持っおいたす。 しかし、私は敬意を衚しお反察したす。 HashCodeは、可倉構造䜓の萜ずし穎を避けるために䞍倉に保぀必芁があるず思いたす。 たた、これのためにIEnumerableを実装する必芁があるのは、ちょっず人工的で䞍安定なようです。 誰かがファむルにusing System.Linqディレクティブを持っおいる堎合、 HashCode暪にドットを眮くず、 Cast<>ずOfType<>が拡匵メ゜ッドずしお衚瀺されたす。 私たちは珟圚の提案にもっず近づくべきだず思いたす。

@jamesqo 、私は同意したす-したがっお、それに぀いお蚀及するこずさえ躊躇したす。 私が気に入っおいるのは、䜿甚法が連鎖よりもクリヌンであるずいうこずだけですが、サンプルの䜿甚法を芋ずにコレクション初期化子を䜿甚できるかどうかが明確でないため、それ自䜓が別の欠点です。

@ MadsTorgersen 、 @ jaredpar 、コレクション初期化子がIEnumerable \の実装を必芁ずする理由䞊蚘の@justinvpの3番目のコメント。

@jamesqo 、私はこれを䞍倉に保぀方が良いこずに同意したすIEnumerableではありたせん\

@mellinoeこれにより、単玔なケヌスが少し単玔になるず思いたすが、それ以䞊のこずはさらに耇雑になりたすそしお、䜕をするのが正しいかに぀いおはあたり明確ではありたせん。

これには以䞋が含たれたす

  1. あなたが過負荷を持っおいるよりも倚くのアむテム
  2. 条件
  3. ルヌプ
  4. 比范噚を䜿甚する

このトピックに぀いお以前に投皿されたASP.NETのコヌド珟圚の提案に曎新に぀いお考えおみたす。

`` `c
var hashCode = HashCode
.CreateIsMainPage
.CombineViewName、StringComparer.Ordinal
.CombineControllerName、StringComparer.Ordinal
.CombineAreaName、StringComparer.Ordinal;

ifViewLocationExpanderValues= null
{{
foreachViewLocationExpanderValuesのvarアむテム
{{
hashCode = hashCode
.Combineitem.Key、StringComparer.Ordinal
.Combineitem.Value、StringComparer.Ordinal;
}
}

hashCodeを返したす。

How would this look with the original `Hash.CombineHashCodes`? I think it would be:

```c#
var hashCode = Hash.CombineHashCodes(
    IsMainPage,
    StringComparer.Ordinal.GetHashCode(ViewName),
    StringComparer.Ordinal.GetHashCode(ControllerName),
    StringComparer.Ordinal.GetHashCode(AreaName));

if (ViewLocationExpanderValues != null)
{
    foreach (var item in ViewLocationExpanderValues)
    {
        hashCode = Hash.CombineHashCodes(
            hashCode
            StringComparer.Ordinal.GetHashCode(item.Key),
            StringComparer.Ordinal.GetHashCode(item.Value));
    }
}

return hashCode;

カスタム比范子に察しおGetHashCode()を呌び出すこずを無芖しおも、最初のパラメヌタヌずしおhashCode以前の倀を枡す必芁があるこずがわかりたす。

@KrzysztofCwalina Cプログラミング蚀語1の@ericlippertのメモによるず、コレクション初期化子は圓然のこずながらコレクション䜜成のためのシンタックスシュガヌであり、算術挔算 Addずいう名前のメ゜ッドの他の䞀般的な䜿甚法ではないためです

1 Googleブックスの仕組みにより、そのリンクがすべおの人に圹立぀ずは限りたせん。

@KrzysztofCwalina、およびノヌトでは、それは非ゞェネリック必芁ですIEnumerable 、ないIEnumerable<T> 。

@ svick 、䞊蚘の最初の䟋のマむナヌニット .Combineぞの最初の呌び出しは、珟圚の提案では.Createになりたす。 ネストされたアプロヌチを䜿甚しない限り。

@svick

それはたた、それを超えるものをより耇雑にするでしょうそしお䜕をするのが正しいかに぀いおはあたり明確ではありたせん

わかりたせん。2番目の䟋は最初の䟋ず党䜓的にほずんど違いがなく、IMOはそれほど耇雑ではありたせん。 2番目/元のアプロヌチでは、䞀連のハッシュコヌドを枡すだけなので最初のパラメヌタヌは実際にはIsMainPage.GetHashCode()必芁があるず思いたす、私には簡単に思えたす。 しかし、私はここでは少数掟のようですので、元のアプロヌチを掚し進める぀もりはありたせん。 私には匷い意芋はありたせん。 これらの䟋はどちらも私には十分合理的に芋えたす。

@justinvpありがずう、曎新されたした。 私は最初の投皿で最初の提案を行いたしたが、それが叀くなっおいるこずに気づいおいたせんでした。誰かがおそらくそれを曎新する必芁がありたす。

@mellinoe問題は、実際には2番目が埮劙なバグを生成する可胜性があるこずです。 これは、私たちのプロゞェクトの1぀からの実際のコヌドです。

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public int GetHashCode(PageFromScratchBuffer obj)
        {
            int v = Hashing.Combine(obj.NumberOfPages, obj.ScratchFileNumber);
            int w = Hashing.Combine(obj.Size.GetHashCode(), obj.PositionInScratchBuffer.GetHashCode());
            return Hashing.Combine(v, w);            
        }

私たちはそれず䞀緒に暮らしおいたすが、私たちは毎日非垞に䜎レベルのものを扱っおいたす。 確かに平均的な開発者ではありたせん。 ただし、ここでは、vずwを組み合わせるよりもvずwを組み合わせるのは同じではありたせん... vずwの組み合わせの間で同じです。 ハッシュの組み合わせは可換ではないため、次々にチェヌンするこずで、APIレベルで䞀連の゚ラヌ党䜓を実際に取り陀くこずができたす。

私は最初の投皿で最初の提案を行いたしたが、それが叀くなっおいるこずに気づいおいたせんでした。おそらく誰かがそれを曎新する必芁がありたす。

終わり。
ずころでこの提案は、特に投祚を远跡するのが非垞に難しいです...非垞に倚くのバリ゚ヌション私は良いず思いたす;-)

@karelz Create APIを远加しおも、 Empty远加できるず思いたす。 @bartonjsが蚀ったように、どちらかである必芁はありたせん。 提案

namespace System
{
    public struct HashCode : IEquatable<HashCode>
    {
        public HashCode();

        public static HashCode Empty { get; }

        public static HashCode Create(int hashCode);
        public static HashCode Create<T>(T value);
        public static HashCode Create<T>(T value, IEqualityComparer<T> comparer);

        public HashCode Combine(int hashCode);
        public HashCode Combine<T>(T value);
        public HashCode Combine<T>(T value, IEqualityComparer<T> comparer);

        public int Value { get; }

        public static implicit operator int(HashCode hashCode);

        public static bool operator ==(HashCode left, HashCode right);
        public static bool operator !=(HashCode left, HashCode right);

        public bool Equals(HashCode other);
        public override bool Equals(object obj);
        public override int GetHashCode();
        public override string ToString();
    }
}

@JonHanna

それはたた、貧匱なシヌドになる傟向があるれロでシヌドする人々を思いずどたらせたす。

遞択するハッシュアルゎリズムは、今日HashHelpers䜿甚されおいるものず同じであり、 hash(0, x) == xずいう効果がありたす。 HashCode.Empty.Combine(x)は、 HashCode.Create(x)ずたったく同じ結果を生成するため、客芳的に違いはありたせん。

@jamesqo最埌の提案に远加のZeroを含めるのを忘れたした。 それが省略だった堎合、曎新できたすか その埌、最新の提案に投祚するように人々に䟝頌するこずができたす。 他の遞択肢私が曎新したトップの投皿を参照はそれほどフォロヌされおいないようです...

@karelz発芋しおくれおありがずう、修正。

@KrzysztofCwalinaは、他の意味ではなく、コレクションに远加するずいう意味で「远加」を意味しおいるこずを確認したす。 この制限が奜きかどうかはわかりたせんが、それが圓時私たちが決めたものです。

public static HashCode Create(int hash);
public HashCode Combine(int hash);

パラメヌタは名前を付ける必芁がありたすhashCodeの代わりにhash枡された倀は、おそらく呌び出しから取埗したハッシュコヌドになるだろうされおいるのでGetHashCode() 

Empty / Zero

これを維持するこずになった堎合、考慮すべき別の名前はDefaultです。

@justinvp

枡される倀はGetHashCodeの呌び出しから取埗される可胜性が高いハッシュコヌドになるため、パラメヌタヌにはハッシュではなくハッシュコヌドずいう名前を付ける必芁がありたすか

intパラメヌタヌにhashずHashCodeパラメヌタヌにhashCodeずいう名前を付けたいず思いたした。 しかし、考え盎しおみるず、あなたが蚀ったように、 hashはちょっず挠然ずしおいるので、 hashCode方が良いず思いたす。 APIを曎新したす。

これを維持するこずになった堎合、考慮すべき別の名前はDefaultです。

Defaultず聞いたずき、「構造䜓のデフォルト倀」ではなく、「遞択するオプションがわからないずきに䜕かをする通垞の方法」だず思いたす。 たずえば、 Encoding.Defaultようなものは、たったく異なる意味合いを持っおいたす。

遞択するハッシュアルゎリズムは、今日のHashHelpersで䜿甚されおいるものず同じであり、hash0、x== xずいう効果がありたす。 HashCode.Empty.Combinexは、HashCode.Createxずたったく同じ結果を生成するため、客芳的に違いはありたせん。

この内郚に぀いおあたり知らない人ずしお、私はHashCode.Create(x).Combine(...)シンプルさが本圓に奜きです。 Createは他の倚くの堎所で䜿甚されおいるため、非垞に明癜です。

Empty / Zero / Defaultがアルゎリズムの䜿甚法を提䟛しない堎合、IMOは存圚しないはずです。

PS非垞に興味深いスレッド!! よくできた 👍

@ cwe1ss

Empty / Zero / Defaultがアルゎリズムの䜿甚法を提䟛しない堎合、IMOは存圚しないはずです。

Emptyフィヌルドがあるず、アルゎリズムを䜿甚できたす。 これは、ハッシュを組み合わせるこずができる「開始倀」を衚したす。 たずえば、 Create厳密に䜿甚しおハッシュの配列を結合する堎合、かなり苊痛になりたす。

int CombineRange(int[] hashes)
{
    if (hashes.Length == 0)
    {
        return 0;
    }

    var result = HashCode.Create(hashes[0]);

    for (int i = 1; i < hashes.Length; i++)
    {
        result = result.Combine(hashes[i]);
    }

    return result;
}

Empty堎合、それははるかに自然になりたす。

int CombineRange(int[] hashes)
{
    var result = HashCode.Empty;

    for (int i = 0; i < hashes.Length; i++)
    {
        result = result.Combine(hashes[i]);
    }

    return result;
}

// or

int CombineRange(int[] hashes)
{
    return hashes.Aggregate(HashCode.Empty, (hc, next) => hc.Combine(next));
}

@terrajobstこのタむプは、私にずっおImmutableArray<T>によく䌌おいたす。 空の配列自䜓はあたり圹に立ちたせんが、他の操䜜の「開始点」ずしお非垞に圹立ちたす。そのため、 Emptyプロパティがありたす。 HashCodeでCreate保持しおいたす。

@jamesqo提案https://github.com/dotnet/corefx/issues/8034#issuecomment-262661653で、あなたが黙っお/誀っお匕数名objをvalueに倉曎したこずに気づきたした。 私はそれをobjに戻したした。これにより、IMOはあなたが埗たものをよりよく捉えたす。 名前valueは、このコンテキストでは「int」ハッシュ倀自䜓ずより関連性がありたす。
必芁に応じおarg名に぀いおさらに議論するこずもできたすが、意図的に倉曎しお、最埌に承認された提案ずの差分を远跡したしょう。

䞊郚の提案を曎新したした。 たた、提案の最埌に承認されたバヌゞョンに察する差分を呌び出したした。

私たちが遞択するハッシュアルゎリズムは、今日のHashHelpersで䜿甚されおいるものず同じになりたす

どこでも䜿甚する必芁があるアルゎリズムずしお遞択するのが良いアルゎリズムであるのはなぜですか 結合されおいるハッシュコヌドに぀いおどのような仮定をしたすか どこでも䜿甚されおいる堎合、DDoS攻撃の新しい道が開かれるのでしょうか。 過去に文字列ハッシュのためにこれによっお焌かれたこずに泚意しおください。

ASP.NETCoreの可倉HashCodeCombiner「ビルダヌ」に沿っお䜕かをした堎合はどうなりたすか

これが正しいパタヌンだず思いたす。 優れたナニバヌサルハッシュコヌドコンバむナヌは、通垞、ハッシュコヌド自䜓に適合する状態よりも倚くの状態を䜿甚できたすが、より倧きな構造䜓を枡すこずはパフォヌマンスの問題であるため、流暢なパタヌンは厩壊したす。

どこでも䜿甚する必芁があるアルゎリズムずしお遞択するのが良いアルゎリズムであるのはなぜですか

どこでも䜿甚するべきではありたせん。 https://github.com/dotnet/corefx/issues/8034#issuecomment-260790829で私のコメントを参照しお

結合されおいるハッシュコヌドに぀いおどのような仮定をしたすか どこでも䜿甚されおいる堎合、DDoS攻撃の新しい道が開かれるのでしょうか。

珟圚のハッシュの問題の1぀は、 hash(0, x) == xです。 したがっお、䞀連のnullたたはれロがハッシュに䟛絊された堎合、それは0のたたになりたす。ここのようたす。これにより、れロかられロぞのマッピングを回避するための魔法の定数が远加されたす。

これが正しいパタヌンだず思いたす。 優れたナニバヌサルハッシュコヌドコンバむナヌは、通垞、ハッシュコヌド自䜓に適合する状態よりも倚くの状態を䜿甚できたすが、より倧きな構造䜓を枡すこずはパフォヌマンスの問題であるため、流暢なパタヌンは厩壊したす。

すべおのナヌスケヌスに適合しようずする倧きな構造䜓サむズのナニバヌサルコンバむナヌがあるべきではないず思いたす。 代わりに、すべおintサむズ FnvHashCodeなどで、すべお独自のCombineメ゜ッドを持぀個別のハッシュコヌドタむプを想定しおいたした。 その䞊、これらの「ビルダヌ」タむプは、ずにかく同じメ゜ッドで保持され、枡されたせん。

すべおのナヌスケヌスに適合しようずする倧きな構造䜓サむズのナニバヌサルコンバむナヌがあるべきではないず思いたす。

ASP.NET Coreは、独自のハッシュコヌドコンバむナヌ珟圚64ビットの状態をこれに眮き換えるこずができたすか

私は、すべおintサむズの個別のハッシュコヌドタむプFnvHashCodeなどを想定しおいたした。

これは組み合わせ爆発に぀ながりたせんか このAPI蚭蚈が䜕に぀ながるかを明確にするこずは、API提案の䞀郚である必芁がありたす。

@jkotas私は議論の始めに同様の反察意芋を述べたした。 ハッシュ関数を扱うには、䞻題に関する知識が必芁です。 しかし、私は、フレヌムワヌクの根底にハッシュコヌドを導入するこずで、2001幎に発生した問題の修正を理解し、サポヌトしたす。ハッシュを組み合わせるレシピを芏定しおいたせん。 この蚭蚈は、99のケヌスでそれを解決するこずを目的ずしおいたすハッシュの統蚈的特性が十分であるため、䞻題の知識が利甚できないか、必芁でさえありたせん。 ASP.Net Coreは、このようなコンバむナヌを、ここで説明するために提案されおいるような非システムアセンブリ䞊の汎甚フレヌムワヌクに含めるこずができるはずです https 

99のケヌスで簡単に䜿甚できるハッシュコヌドコンバむナヌを甚意するこずをお勧めしたす。 ただし、32ビットだけでなくより倚くの内郚状態を考慮に入れる必芁がありたす。

ずころでASP.NETは元々ハッシュコヌドの結合に流暢なパタヌンを䜿甚しおいたしたが、バグを芋逃しやすいため、それをやめたした https 

ハッシュフラッディングセキュリティに関する@jkotas 。
免責事項専門家ではありたせん専門家に盞談する必芁がありたす。MSはこの問題に぀いお数人以䞊いたす 。

私は呚りを芋回しおおり、この問題に関する䞀般的なコンセンサスはありたせんが、最近泚目を集めおいる議論がありたす。 ハッシュコヌドは32ビットサむズです。セットのサむズが䞎えられた堎合の衝突の確率を瀺すグラフの前に投皿したした。 ぀たり、アルゎリズムがどれほど優れおいおもたずえば、SipHashを芋るず、劥圓な時間1時間未満で話すで倧量のハッシュを生成しお衝突を芋぀けるこずがかなり実行可胜です。 これらの問題は、ハッシュを保持するデヌタ構造で察凊する必芁があり、ハッシュ関数レベルでは解決できたせん。 基になるデヌタ構造を修正せずにハッシュフラッディングから保護するために非暗号化で远加のパフォヌマンスを支払っおも、問題は解決されたせん。

線集あなたは私が曞いおいる間に投皿したした。 これに照らしお、64ビット状態はあなたにずっお䜕を埗るのですか

@jkotasあなたがリンクしおいる問題を調べたした。 それは蚀う

aspnet / Common40ぞの反応

https://github.com/aspnet/Common/issues/40の説明

バグを芋぀ける

public class TagBuilder
{
    private Dictionary<string, string> _attributes;
    private string _tagName;
    private string _innerContent;

    public override int GetHashCode()
    {
        var hash = HashCodeCombiner.Start()
            .Add(_tagName, StringComparer.Ordinal)
            .Add(_innerContent, StringComparer.Ordinal);

        foreach (var kvp in _attributes)
        {
            hash.Add(kvp.Key, StringComparer.Ordinal).Add(kvp.Value, StringComparer.Ordinal);
        }

        return hash.Build();
    }
}

来お。 その匕数は、 Substringが新しい文字列を返すこずに人々が気付いおいないため、 stringは倉曎可胜である必芁があるず蚀っおいるようなものです。 可倉構造䜓は、萜ずし穎の点ではるかに悪いです。 構造䜓を䞍倉に保぀べきだず思いたす。

ハッシュフラッディングセキュリティに関しお。

これには2぀の偎面がありたす。構築による修正蚭蚈堅牢なデヌタ構造など。 既存の蚭蚈の問題の軜枛。 どちらも重芁です。

@karelzパラメヌタの呜名に぀いお

あなたが黙っお/偶然にあなたの提案dotnet / corefx8034コメントでarg nameobjをvalueに倉曎したこずに気づきたした。 私はそれをobjに戻したした。これは、IMOが取埗したものをより適切にキャプチャしたす。 このコンテキストでは、名前の倀は「int」ハッシュ倀自䜓ずより関連性がありたす。
必芁に応じおarg名に぀いおさらに議論するこずもできたすが、意図的に倉曎しお、最埌に承認された提案ずの差分を远跡したしょう。

将来の提案では、倀をたずめお組み合わせるためのAPIを远加するこずを怜蚎しおいたす。 䟋 CombineRange(ReadOnlySpan<T>) 。 これにobjずいう名前を付けた堎合、パラメヌタにobjsずいう名前を付ける必芁がありたすが、これは非垞に厄介に聞こえたす。 したがっお、代わりにitemずいう名前を付ける必芁がありたす。 将来的には、スパンパラメヌタにitemsずいう名前を付けるこずができたす。 提案を曎新したした。

@jkotasは同意したすが、ここでのポむントは、コンバむナヌレベルでは䜕も軜枛しおいないずいうこずです...

私たちができる唯䞀のこずは、ランダムシヌドを持぀こずです。これは、すべおの状態ず目的で、コヌドをstringで芋たこずを芚えおおり、ビルドごずに固定されおいたす。 それはずっず前だったので、それに぀いお間違っおいる可胜性がありたす。 ランダムシヌドを適切に実装するこずが、ここで適甚できる唯䞀の緩和策です。

これは課題です。固定のランダムシヌドを䜿甚した最高の文字列やメモリハッシュ関数を教えおください。衝突のみを生成する32ビットハッシュコヌドのセットを䜜成したす。 非垞に簡単にできるので、私はそのような挑戊をするこずを恐れたせん。確率論は私の偎にありたす。 私も行っお賭けをしたすが、私はそれに勝぀こずを知っおいるので、それは本質的にもう賭けではありたせん。

さらに...より深い分析では、軜枛策が実行ごずにこれらの「ランダムシヌド」​​を組み蟌む機胜であっおも、より耇雑なコンバむナヌは必芁ないこずが瀺されおいたす。 基本的に、゜ヌスで問題を軜枛したためです。

M1ずM2 、ランダムシヌドが異なるrs1ずrs2たす。
M1はh1 = hash('a', rs1)ずh2=hash('b', rs1)を発行したす
M2はh1' = hash('a', rs2)ずh2'=hash('b', rs2)を発行したす
ここで重芁な点は、 h1ずh1'は確率1/ (int.MaxInt-1)  hashで十分な堎合で異なり、すべおの目的で次のようになるこずです。それが埗られるので良い。
したがっお、十分に良い堎合䜿甚するこずにしたc(x,y)は、゜ヌスに組み蟌たれおいる緩和策をすでに考慮に入れおいたす。

線集私はコヌドを芋぀けたした、あなたは今各ドメむンで倉わるMarvin32を䜿甚しおいたす。 したがっお、文字列の緩和策は、実行ごずにランダムシヌドを䜿甚するこずです。 私が述べたように、これは十分な緩和策です。

@jkotas

ASP.NET Coreは、独自のハッシュコヌドコンバむナヌ珟圚64ビットの状態をこれに眮き換えるこずができたすか

絶察; 同じハッシュアルゎリズムを䜿甚したす。 このテストアプリを䜜成し

私は、すべおintサむズの個別のハッシュコヌドタむプFnvHashCodeなどを想定しおいたした。

これは組み合わせ爆発に぀ながりたせんか このAPI蚭蚈が䜕に぀ながるかを明確にするこずは、API提案の䞀郚である必芁がありたす。

@jkotas 、そうではありたせん。 このクラスの蚭蚈は、将来のハッシュAPIの蚭蚈を決定するものではありたせん。 これらは、より高床なシナリオず芋なす必芁があり、dotnet / corefx13757などの別の提案を行う必芁があり、別の蚭蚈に関する議論が行われたす。 GetHashCodeオヌバヌラむドに苊劎しおいる初心者のために、䞀般的なハッシュアルゎリズム甚のシンプルなAPIを甚意するこずがはるかに重芁だず思いたす。

99のケヌスで簡単に䜿甚できるハッシュコヌドコンバむナヌを甚意するこずをお勧めしたす。 ただし、32ビットだけでなくより倚くの内郚状態を考慮に入れる必芁がありたす。

32ビットよりも倚くの内郚状態が必芁になるのはい぀ですか 線集人々がカスタムハッシュロゞックをプラグむンできるようにする堎合、それは再び高床なシナリオず芋なされ、dotnet / corefx13757で説明されるべきだず思いたす。

珟圚、各ドメむンで倉曎されおいるMarvin32を䜿甚しおいたす

そうです、文字列ハッシュコヌドのランダム化の軜枛は、.NETCoreではデフォルトで有効になっおいたす。 互換性があるため、完党な.NETFrameworkのスタンドアロンアプリではデフォルトで有効になっおいたせん。 癖を介しおのみ有効になりたすたずえば、リスクの高い環境で。

.NET Coreには、ランダム化されおいないハッシュのコヌドがただありたすが、削陀しおも問題ありたせん。 再び必芁になるずは思いたせん。 たた、ランダム化されおいないパスを䜿甚するかどうかのチェックが行われないため、文字列ハッシュコヌドの蚈算が少し速くなりたす。

ランダム化された文字列ハッシュコヌドの蚈算に䜿甚されるMarvin32アルゎリズムには、64ビットの内郚状態がありたす。 これは、MSの察象分野の専門家によっお遞ばれたした。 私は圌らが64ビットの内郚状態を䜿甚する正圓な理由を持っおいたず確信しおいたす、そしお圌らは物事を遅くするためだけにそれを䜿甚しおいたせん。

汎甚ハッシュコンバむナヌは、この緩和策を進化させ続ける必芁がありたす。ランダムシヌドず十分に匷力なハッシュコヌド結合アルゎリズムを䜿甚する必芁がありたす。 理想的には、ランダム化された文字列ハッシュず同じMarvin32を䜿甚したす。

ランダム化された文字列ハッシュコヌドの蚈算に䜿甚されるMarvin32アルゎリズムには、64ビットの内郚状態がありたす。 これは、MSの察象分野の専門家によっお遞ばれたした。 私は圌らが64ビットの内郚状態を䜿甚する正圓な理由を持っおいたず確信しおいたす、そしお圌らは物事を遅くするためだけにそれを䜿甚しおいたせん。

@jkotas 、リンクしたハッシュコヌドコンバむナヌはMarvin32を䜿甚しおいたせん。 ランダム化されおいないstring.GetHashCode䜿甚されおいるのず同じ単玔なDJBx33xアルゎリズムを䜿甚したす。

汎甚ハッシュコンバむナヌは、この緩和策を進化させ続ける必芁がありたす。ランダムシヌドず十分に匷力なハッシュコヌド結合アルゎリズムを䜿甚する必芁がありたす。 理想的には、ランダム化された文字列ハッシュず同じMarvin32を䜿甚したす。

このタむプは、ハッシュDoS攻撃を受けやすい堎所での䜿甚を目的ずしたものではありたせん。 これは、add / xorをよく知らない人を察象ずしおおり、 https//github.com/dotnet/coreclr/pull/4654のようなものを防ぐのに圹立ち

汎甚ハッシュコンバむナヌは、この緩和策を進化させ続ける必芁がありたす。ランダムシヌドず十分に匷力なハッシュコヌド結合アルゎリズムを䜿甚する必芁がありたす。 理想的には、ランダム化された文字列ハッシュず同じMarvin32を䜿甚したす。

次に、Cチヌムず話し合っお、軜枛されたValueTupleハッシュアルゎリズムを実装する必芁がありたす。 そのコヌドはリスクの高い環境でも䜿甚されるためです。 そしおもちろん、 Tuple https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Tuple.cs#L60たたはSystem.Numerics.HashHelpers 堎所。

さお、それを実装する方法を決定する前に、完党にランダム化されたハッシュコヌド結合アルゎリズムのコストを支払う䟡倀があるかどうかもちろん存圚する堎合、APIの方法を倉曎しない堎合でも、同じ察象分野の専門家を調べたすどちらかを蚭蚈したした提案されたAPIの䞋では、512ビットの状態を䜿甚できたすが、もちろん、そのコストを支払う意思がある堎合は、同じパブリックAPIを䜿甚できたす。

これは、远加/排他的論理和をよく知らない人を察象ずしおいたす

それが堅牢であるこずが重芁である理由です。 .NETの重芁な䟡倀は、よく知らない人々の問題に察凊するこずです。

そしお、私たちがそれに取り組んでいる間、 IntPtr忘れないでくださいhttps://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/IntPtr.cs#L119
badはdabず衝突するため、これは特に厄介です。xorはおそらく最悪です。

軜枛されたValueTupleハッシュアルゎリズムを実装する

いい芖点ね。 ValueTupleが出荷されたのか、それずもただこれを行う時期なのかはわかりたせん。 https://github.com/dotnet/corefx/issues/14046を開きたした

IntPtrを忘れないでください

これらは過去の過ちです...それらを修正するための基準ははるかに高くなっおいたす。

@jkotas

これらは過去の過ちです...それらを修正するための基準ははるかに高くなっおいたす。

.Net Coreのポむントの1぀は、そのような「小さな」倉曎の基準がはるかに䜎くなるはずだずいうこずです。 誰かがIntPtr.GetHashCodeの実装に䟝存しおいる堎合実際にはそうすべきではありたせん、. NetCoreのバヌゞョンをアップグレヌドしないこずを遞択できたす。

そのような「小さな」倉化のバヌははるかに䜎くなるはずです

はい、それは-完党な.NETFrameworkず比范しおです。 ただし、倉曎をシステムにプッシュするための䜜業を行う必芁があり、苊劎するだけの䟡倀がないこずに気付く堎合がありたす。 最近の䟋は、Fが壊れたために元に戻されたTuple<T>ハッシュアルゎリズムの倉曎です https 

@jkotas

HashCode 64ビットにする堎合、䞍倉の蚭蚈で32ビット環境のパフォヌマンスが䜎䞋するず思いたすか 私は他の読者に同意したす、ビルダヌパタヌンははるかに悪いようです。

パフォヌマンスを殺す-いいえ。 シンタックスシュガヌに支払われるパフォヌマンスペナルティ-はい。

シンタックスシュガヌに支払われるパフォヌマンスペナルティ-はい。

将来、JITによっお最適化できるものですか

パフォヌマンスを殺したす-いいえ。
シンタックスシュガヌに支払われるパフォヌマンスペナルティ-はい。

糖衣構文以䞊のものです。 HashCodeをクラスにするこずをいずわないのであれば、それはシンタックスシュガヌになりたす。 しかし、可倉倀型はバグファヌムです。

以前からの匕甚

それが堅牢であるこずが重芁である理由です。 .NETの重芁な䟡倀は、よく知らない人々の問題に察凊するこずです。

可倉倀型は、よく知らない倧倚数の人々にずっお堅牢なAPIではないず私は䞻匵したす。

可倉倀型は、よく知らない倧倚数の人々にずっお堅牢なAPIではないず私は䞻匵したす。

同意。 ずはいえ、可倉構造䜓ビルダヌタむプの堎合は残念だず思いたす。 私が䜿甚し、それらをすべおの時間を、圌らは玠晎らしく、締たっおいるのです。 [MustNotCopy]泚釈は誰ですか

MustNotCopyは、構造䜓愛奜家の倢が叶うものです。 @jaredpar

MustNotCopyはスタックのみのようなものですが、䜿甚するのはさらに困難です😄

クラスを䜜成せずに、ハッシュを組み合わせるための拡匵メ゜ッドを䜜成するこずをお勧めしたす

static class HashHelpers
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static int CombineHash(this int hash1, int hash2);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static int CombineHash<T>(this int hash, T value);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static int CombineHash<T>(this int hash, T value, IEqualityComparer<T> comparer);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static int CombineHash<T>(this int hash, IEnumerable<T> values);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static int CombineHash<T>(this int hash, IEnumerable<T> values, IEqualityComparer<T> comparer);
}

以䞊です 高速で䜿いやすいです。

@AlexRadchハッシュずしお意図されたものだけでなく、すべおの敎数のメ゜ッドリストを汚染するのは奜きではありたせん。

たた、ハッシュコヌドの蚈算のチェヌンを継続するメ゜ッドがありたすが、どのように開始したすか れロから始めるなど、自明ではないこずをする必芁がありたすか ぀たり、 0.CombineHash(this.FirstName).CombineHash(this.LastName) 。

曎新dotnet / corefx14046のコメントによるず、既存のハッシュ匏はValueTuple保持されるこずが決定されたした

@jamesqo助けおくれおありがずう。
@jkotasず進めおもかたいたせんが、より高䟡なハッシュ関数の採甚を控えたいず
ランダム化を行うこずで、必芁が生じた堎合に将来ハッシュ関数を倉曎するための扉が開かれたす。

@jkotas 、珟圚のROL 5ベヌスのハッシュをHashCodeたたにしお、4バむトに瞮小するこずはできたすか これにより、構造䜓のコピヌに関するすべおの問題が解消されたす。 HashCode.Emptyランダム化されたハッシュ倀を衚すこずができたす。

@svick
はい、これはすべおの敎数のメ゜ッドを汚染したすが、分離された名前空間に配眮するこずができ、ハッシュを䜿甚しない堎合は、それを含めず、衚瀺されたせん。

0.CombineHash(this.FirstName).CombineHash(this.LastName)はthis.FirstName.GetHash().CombineHash(this.LastName)ず曞く必芁がありたす

シヌドから開始しお実装するには、次の静的メ゜ッドを䜿甚できたす

static class HashHelpers
{
    public static int ClassSeed<T>();
}

class SomeClass
{
    int GetHash()
    {
        return HashHelpers.ClassSeed<SomeClass>().CombineHash(value1).CombineHash(value2);
    }
}

したがっお、各クラスには、ハッシュをランダム化するための異なるシヌドがありたす。

@ jkotas 、

パブリックプラットフォヌムのハッシュコヌド構築ヘルパヌは、堅牢にするために64ビット状態を䜿甚する必芁があるず思いたす。 32ビットのみの堎合、特により倚くの芁玠、配列、たたはコレクションをハッシュするために䜿甚するず、悪い結果が生じる傟向がありたす。 䜿甚するのが良いのか、䜿甚しないのが良いのかに぀いお、どのようにドキュメントを䜜成したすか はい、それはビットを混合するために費やされる䜙分な指瀺ですが、私はそれが重芁であるずは思いたせん。 これらの皮類の呜什は超高速で実行されたす。 私の経隓では、ビットミキシングが少なすぎるず、倚すぎるよりもはるかに深刻になるため、ビットミキシングを少なくするよりも倚くする方がよいず思いたす。

たた、提案されおいるAPIの圢状に぀いおも懞念がありたす。 問題はハッシュコヌドの組み合わせではなく、ハッシュコヌドの構築ずしお考えるべきだず思いたす。 これをプラットフォヌムAPIずしお远加するのは時期尚早かもしれたせん。むしろ、これに察しおより良いパタヌンが出珟するかどうかを確認する必芁がありたす。 これは、誰かがこのAPIを䜿甚しお゜ヌスnugetパッケヌゞを公開したり、corefxがそれを内郚ヘルパヌずしお䜿甚したりするこずを劚げるものではありたせん。

64ビット状態の64ビット状態を䜿甚するように蚭蚈する必芁がありたす。 たた、結合機胜が良ければ統蚈的に蚀えば、混合が少ないずいうこずはありたせん。 ハッシュにランダム化、アバランシェ、およびその他の関心のある統蚈的特性がある堎合、技術的には特別に现工されたハッシュ関数であるため、混合が考慮されたす。

優れたハッシュ関数を䜜成するものを確認しおください明らかにxorようなものもありたす http  https://research.neustar.biz/2012/02/02/choosing-a-good-hash-function-part-3/

@jamesqoずころで、「シヌドは毎回倉曎されるため、実際にはランタむムハッシュではなくハッシュを結合しおいる」堎合には、コンバむナヌが機胜しないこずに気付きたした。 ...シヌドを持぀パブリックコンストラクタ

@jkotas

パブリックプラットフォヌムのハッシュコヌド構築ヘルパヌは、堅牢にするために64ビット状態を䜿甚する必芁があるず思いたす。 32ビットのみの堎合、特により倚くの芁玠、配列、たたはコレクションをハッシュするために䜿甚するず、悪い結果が生じる傟向がありたす。

最終的に単䞀のintに凝瞮される堎合、これは重芁ですか

@jamesqo実際には、状態のサむズは機胜のみに䟝存し、堅牢性には䟝存したせん。 実際、コンバむンがそのように機胜するように蚭蚈されおいない堎合、ハッシュ関数を実際に悪化させる可胜性がありたす。匷制からランダム性を取埗できないため、せいぜいリ゜ヌスを浪費しおいたす。

圓然の結果関数が統蚈的に優れおいるこずを確認する必芁がありたす。そうしないず、関数が悪化するこずがほが保蚌されたす。

これは、アむテム間に盞関関係があるかどうかによっお異なりたす。 盞関関係がない堎合は、32ビット状態ず単玔なrotlたたはxorで問題なく動䜜したす。 盞関関係があるかどうかによりたす。

誰かがこれを䜿甚しお、個々の文字から文字列ハッシュコヌドを䜜成したかどうかを怜蚎しおください。 誰かが実際に文字列に察しおこれを行う可胜性が高いずいうわけではありたせんが、問題を瀺しおいたす。

for (int i = 0; i < str.Length; i++)
   hashCodeBuilder.Add(str[i]);

実䞖界の文字列の文字は盞関する傟向があるため、32ビット状態の文字列ず単玔なrotlの結果は良くありたせん。 これが盞関するために䜿甚されるアむテムはどのくらいの頻床で、どのくらい悪い結果になりたすか 実生掻では物事は予想倖の方法で盞関する傟向がありたすが、わかりにくいです。

APIサポヌトハッシュランダム化に次のメ゜ッドを远加するのは玠晎らしいこずです。

namespace System
{
    public struct HashCode : IEquatable<HashCode>
    {
       // add this
       public static HashCode CreateRandomized(Type type);
       // or add this
       public static HashCode CreateRandomized<T>();
    }
}

@jkotasただテストしおいないので、テストしたず思いたす。 しかし、それは間違いなく私たちが䜿甚しようずしおいる関数に぀いお䜕かを蚀っおいたす。 速床ず信頌性を亀換したい堎合は、少なくずも十分ではありたせん誰もそれを䜿っお愚かなこずをするこずはできたせん。 私はか぀お、これは非暗号化ハッシュ関数ではなく、無盞関のハッシュコヌド取埗するのず同じくらいランダムを組み合わせるための高速な方法であるずいう蚭蚈を支持しおいたす。

私たちが目指しおいるのは、誰もそれで愚かなこずをしないずいうこずです。64ビット状態を䜿甚しおも䜕も修正されたせん。問題を隠しおいるだけです。 その盞関関係を利甚する入力を䜜成するこずは匕き続き可胜です。 これは、私が18日前に行ったのずたったく同じ議論をもう䞀床指摘したす。 参照 https 

私はか぀お、これは非暗号化ハッシュ関数ではなく、無盞関のハッシュコヌドを組み合わせるための高速な方法であるずいう蚭蚈を支持しおいたす

無盞関のハッシュコヌドを組み合わせる最速の方法は、xor ...です。

本圓ですが、前回はあたりうたく機胜しなかったこずを私たちは知っおいたすIntPtrが私の頭に浮かびたす。 回転ずXOR珟圚は同じくらい高速で、誰かが䜕らかの盞関関係のあるものを入れおも損倱はありたせん。

public static HashCode CreateRandomized(Type type);たたはpublic static HashCode CreateRandomized<T>();メ゜ッド、あるいはその䞡方を䜿甚しおハッシュコヌドのランダム化を远加したす。

@jkotas私はこれのためのより良いパタヌンを芋぀けたかもしれないず思いたす。 C7 ref returnを䜿甚した堎合はどうなりたすか 毎回HashCodeを返す代わりに、レゞスタヌに収たるref HashCodeを返したす。

public struct HashCode
{
    private readonly long _value;

    public ref HashCode Combine(int hashCode)
    {
        CombineCore(ref _value, hashCode); // note: modifies the struct in-place
        return ref this;
    }
}

䜿甚法は以前ず同じです。

return HashCode.Combine(1)
    .Combine(2).Combine(3);

唯䞀の欠点は、再び可倉構造䜓に戻るこずです。 しかし、コピヌず䞍倉性の䞡方を同時に持たない方法はないず思いたす。

 ref thisはただ機胜しおいたせんが、ここで有効にするためのPRがRoslynにあり


@AlexRadch型のハッシュコヌドを取埗するにはコストがかかるため、ハッシュを型ずさらに組み合わせるのは賢明ではないず思いたす。

@jamesqo public static HashCode CreateRandomized<T>();は型ハッシュコヌドを取埗したせん。 このタむプのランダム化されたHashCodeを䜜成したす。

@jamesqo 「 ref thisはただ機胜しおいたせん」。 Roslynの問題が修正された埌でも、しばらくの間、corefxリポゞトリでref thisを䜿甚できなくなりたす @ stephentoubが期埅を蚭定できる期間は

蚭蚈の議論はここでは収束しおいたせん。 さらに、200のコメントをフォロヌするのは非垞に困難です。
来週は@jkotasを取埗し、

䞀方で、この問題を閉じお、来週の「祝犏された提案」で新しい問題を䜜成し、長い議論を続ける負担を軜枛するこずをお勧めしたす。 悪い考えだず思われる堎合はお知らせください。

@jcouvリリヌス時にこのデザむンに埓うこずができる限り、ただ機胜しおいなくおも倧䞈倫です。  Unsafeを䜿甚しお䞀時的にこれを回避するこずも可胜かもしれないず思いたす。

@karelz OKsmile埌で時間があるずきにこの提案を閉じお、新しい提案を開きたす。 同意したす; 私のブラりザは200以䞊のコメントをうたく凊理できたせん。

@karelz私はref this戻り倀を有効にしようずしおいたこずがわかりたした。 ref thisは構造䜓から安党に返すこずはできたせん。 理由に぀いおは、こちらをご芧ください。 したがっお、ref-returningの劥協は機胜したせん。

ずにかく、私はこの問題を閉じたす。 ここで別の問題を開きたした https 

CvNext ...を想定しおいたすが、倀型拡匵メ゜ッドの投皿

@benaadams

CvNextを想定しおいたすが、倀型拡匵メ゜ッドpost dotnet / roslyn15650からref "this"を返すこずができるはずです...

正しい。 ref this拡匵メ゜ッドからthisを返すこずができたす。 ただし、通垞のstructむンスタンスメ゜ッドからthisを返すこずはできたせん。 なぜそうなるのかに぀いおは、生涯の詳现がたくさんありたす:(

@redknightlois

厳密にしたい堎合、ハッシュはuintのみである必芁がありたす。これは、フレヌムワヌクがその光の䞋でint返すずいう芋萜ずしず芋なすこずができたす。

CLS準拠 笊号なし敎数はCLSに準拠しおいたせん。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡