APIã·ã§ã€ããå®æããŸããã ãã ããå®è£ ã«äœ¿çšããåè£ã®ãªã¹ãããæé©ãªããã·ã¥ã¢ã«ãŽãªãºã ããŸã 決å®ããŠãããããåã¢ã«ãŽãªãºã ã®ã¹ã«ãŒããã/åæ£ã枬å®ããã®ãæäŒã£ãŠããã人ãå¿ èŠã§ãã ãã®åœ¹å²ãåŒãåãããå Žåã¯ãäžã«ã³ã¡ã³ããæ®ããŠãã ããã @ karelzããã®åé¡ãå²ãåœãŠãŸãã
ããã§@terrajobstã«ããæ¿èªãããAPIã§ãhttps://github.com/dotnet/corefx/issues/14354#issuecomment -308190321ã¯ïŒ
// Will live in the core assembly
// .NET Framework : mscorlib
// .NET Core : System.Runtime / System.Private.CoreLib
namespace System
{
public struct HashCode
{
public static int Combine<T1>(T1 value1);
public static int Combine<T1, T2>(T1 value1, T2 value2);
public static int Combine<T1, T2, T3>(T1 value1, T2 value2, T3 value3);
public static int Combine<T1, T2, T3, T4>(T1 value1, T2 value2, T3 value3, T4 value4);
public static int Combine<T1, T2, T3, T4, T5>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5);
public static int Combine<T1, T2, T3, T4, T5, T6>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6);
public static int Combine<T1, T2, T3, T4, T5, T6, T7>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7);
public static int Combine<T1, T2, T3, T4, T5, T6, T7, T8>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8);
public void Add<T>(T value);
public void Add<T>(T value, IEqualityComparer<T> comparer);
[Obsolete("Use ToHashCode to retrieve the computed hash code.", error: true)]
[EditorBrowsable(Never)]
public override int GetHashCode();
public int ToHashCode();
}
}
ãã®ææ¡ã®åæã¯æ¬¡ã®ãšããã§ãã
åªããããã·ã¥ã³ãŒããçæããããã«ãéãéæ³ã®å®æ°ã䜿çšããããã³ãŒããå°ãããã£ããããå¿
èŠã¯ãããŸããã 次ã®ãããªæªããç°¡æœãªGetHashCode
å®è£
ãæžãããšã¯ããã»ã©é
åçã§ã¯ãªãã¯ãã§ãã
class Person
{
public override int GetHashCode() => FirstName.GetHashCode() + LastName.GetHashCode();
}
HashCode
ã¿ã€ããè¿œå ããŠãããã·ã¥ã³ãŒãã®äœæãã«ãã»ã«åããéçºè
ãåä»ãªè©³çŽ°ã«æ··ä¹±ããã®ãåé¿ããå¿
èŠããããŸãã ãããç§ã®ææ¡ã§ããããã¯https://github.com/dotnet/corefx/issues/14354#issuecomment-305019329ã«åºã¥ããŠãããããã€ãã®ãã€ããŒãªæ¹èšãå ããããŠããŸãã
// Will live in the core assembly
// .NET Framework : mscorlib
// .NET Core : System.Runtime / System.Private.CoreLib
namespace System
{
public struct HashCode
{
public static int Combine<T1>(T1 value1);
public static int Combine<T1, T2>(T1 value1, T2 value2);
public static int Combine<T1, T2, T3>(T1 value1, T2 value2, T3 value3);
public static int Combine<T1, T2, T3, T4>(T1 value1, T2 value2, T3 value3, T4 value4);
public static int Combine<T1, T2, T3, T4, T5>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5);
public static int Combine<T1, T2, T3, T4, T5, T6>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6);
public static int Combine<T1, T2, T3, T4, T5, T6, T7>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7);
public static int Combine<T1, T2, T3, T4, T5, T6, T7, T8>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8);
public void Add<T>(T value);
public void Add<T>(T value, IEqualityComparer<T> comparer);
public void AddRange<T>(T[] values);
public void AddRange<T>(T[] values, int index, int count);
public void AddRange<T>(T[] values, int index, int count, IEqualityComparer<T> comparer);
[Obsolete("Use ToHashCode to retrieve the computed hash code.", error: true)]
public override int GetHashCode();
public int ToHashCode();
}
}
ã³ã¡ã³ã@terrajobstãåç §ããŠãã ããhttps://github.com/dotnet/corefx/issues/14354#issuecomment -305019329ãã®APIã®ç®çã®ããã«ã 圌ã®çºèšã¯ãã¹ãŠæå¹ã§ãã ãã ããç¹ã«ããããææããããšæããŸãã
ææ¡ïŒããã·ã¥ã©ã³ãã åãµããŒããè¿œå
public static HashCode Randomized<T> { get; } // or CreateRandomized<T>
or
public static HashCode Randomized(Type type); // or CreateRandomized(Type type)
åãã¿ã€ãã®åãã©ã³ãã åããã·ã¥ãååŸããã«ã¯ã T
ãŸãã¯Type type
ãå¿
èŠã§ãã
ææ¡ïŒã³ã¬ã¯ã·ã§ã³ã®ãµããŒããè¿œå ãã
public HashCode Combine<T>(T[] values);
public HashCode Combine<T>(T[] values, IEqualityComparer<T> comparer);
public HashCode Combine<T>(Span<T> values);
public HashCode Combine<T>(Span<T> values, IEqualityComparer<T> comparer);
public HashCode Combine<T>(IEnumerable<T> values);
public HashCode Combine<T>(IEnumerable<T> IEqualityComparer<T> comparer);
次ã®ã³ãŒãHashCode.Empty.Combine(_field1).Combine(_field2).Combine(_field3).Combine(_field4).Combine(_field5);
ã¯ãCombineåŒã³åºããªãã§ã€ã³ã©ã€ã³æé©åããå¿
èŠãããããããªãŒããŒããŒãCombine(_field1, _field2, _field3, _field4, _field5)
ã¯å¿
èŠãªããšæããŸãã
@AlexRadch
ææ¡ïŒã³ã¬ã¯ã·ã§ã³ã®ãµããŒããè¿œå ãã
ã¯ããããã¯ãã®ææ¡ã®æçµçãªèšç»ã®äžéšã§ããã ãã ãããããã®ã¡ãœãããè¿œå ããåã«ãAPIãã©ã®ããã«è¡šç€ºããããã«çŠç¹ãåœãŠãããšãéèŠã ãšæããŸãã
圌ã¯ãcoreclrã®æååã«äœ¿çšãããMarvin32ããã·ã¥ãªã©ãå¥ã®ã¢ã«ãŽãªãºã ã䜿çšããããšèããŠããŸããã ããã«ã¯ãHashCodeã®ãµã€ãºã8ãã€ãã«æ¡åŒµããå¿ èŠããããŸãã
4ãã€ããŸãã¯8ãã€ãçžåœã®ããŒã¿ãå éšã«æ ŒçŽããHash32ããã³Hash64ã¿ã€ããããã®ã¯ã©ãã§ããïŒ ããããã®é·æ/çæãææžåããŸãã Hash64ã¯Xã«ã¯é©ããŠããŸãããé床ãäœäžããå¯èœæ§ããããŸãã Hash32ã®æ¹ãé«éã§ãããåæ£ãããŠããªãå¯èœæ§ããããŸãïŒãŸãã¯å®éã®ãã¬ãŒããªãã¯äœã§ãïŒã
圌ã¯ããã·ã¥ã·ãŒããã©ã³ãã åãããã£ãã®ã§ãããã·ã¥ã¯æ±ºå®è«çã§ã¯ãããŸããã§ããã
ããã¯äŸ¿å©ãªåäœã®ããã§ãã ããããç§ã¯ãããå¶åŸ¡ããã人ã ãèŠãããšãã§ããŸããã ãããã£ãŠãããã·ã¥ãäœæããã«ã¯2ã€ã®æ¹æ³ãå¿ èŠã§ãã1ã€ã¯ã·ãŒããååŸããªãïŒãããŠã©ã³ãã ã·ãŒãã䜿çšããïŒæ¹æ³ã§ããã1ã€ã¯ã·ãŒããæäŸã§ããããã«ããæ¹æ³ã§ãã
泚ïŒRoslynã¯ããããFxã§æäŸãããããšãæãã§ããŸãã ãŠãŒã¶ãŒã«GetHashCodeãåãåºãæ©èœãè¿œå ããŠããŸãã çŸåšã次ã®ãããªã³ãŒããçæããŸãã
c#
public override int GetHashCode()
{
var hashCode = -1923861349;
hashCode = hashCode * -1521134295 + this.b.GetHashCode();
hashCode = hashCode * -1521134295 + this.i.GetHashCode();
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(this.s);
return hashCode;
}
ããã¯çŽ æŽãããçµéšã§ã¯ãªããå€ãã®éãæŠå¿µãæããã«ããŸãã 代ããã«åŒã³åºãããšãã§ããHash.WhateverAPIããããšã¯ã¯ã¯ã¯ããŸãã
ããããšãïŒ
MurmurHashã¯ã©ãã§ããïŒ é©åºŠã«é«éã§ãéåžžã«åªããããã·ã¥ç¹æ§ãåããŠããŸãã ãŸãã2ã€ã®ç°ãªãå®è£ ããããŸãã1ã€ã¯32ãããããã·ã¥ãåãåºããã®ã§ããã1ã€ã¯128ãããããã·ã¥ãåãåºããã®ã§ãã
32ããã圢åŒãš128ããã圢åŒã®äž¡æ¹ã®ãã¯ãã«åãããå®è£ ããããŸãã
@tannergooding MurmurHashã¯é«éã§ããããã®ããã°æçš¿ã®é³ãããããšå®å šã§ã¯ãããŸããã
@jkotas ãæšå¹Žã®è°è«ä»¥æ¥ã32ãããã§4ãã€ããè¶ ããæ§é äœã«å¯ŸããŠããè¯ãã³ãŒããçæããããšã«é¢ããŠJITã§äœãäœæ¥ããããŸãããïŒ ãŸãã @ CyrusNajmabadiã®ææ¡ã«ã€ããŠã©ãæããŸããïŒ
4ãã€ããŸãã¯8ãã€ãçžåœã®ããŒã¿ãå éšã«æ ŒçŽããHash32ããã³Hash64ã¿ã€ããããã®ã¯ã©ãã§ããïŒ ããããã®é·æ/çæãææžåããŸãã Hash64ã¯Xã«ã¯é©ããŠããŸãããé床ãäœäžããå¯èœæ§ããããŸãã Hash32ã®æ¹ãé«éã§ãããåæ£ãããŠããªãå¯èœæ§ããããŸãïŒãŸãã¯å®éã®ãã¬ãŒããªãã¯äœã§ãïŒã
ç§ã¯ãŸã ãã®ã¿ã€ããéçºè ã«æäŸããã®ã«éåžžã«äŸ¡å€ããããšæããŸãããããŠããã2.0ã§ãããæã£ãŠããããšã¯çŽ æŽãããã§ãããã
@jamesqo ããã®å®è£ ã¯æå·çã«å®å šã§ããå¿ èŠã¯ãªããšæããŸãïŒããããæ瀺çãªæå·ããã·ã¥é¢æ°ã®ç®çã§ãïŒã
ãŸãããã®èšäºã¯Murmur2ã«ãé©çšãããŸãã ãã®åé¡ã¯ãMurmur3ã¢ã«ãŽãªãºã ã§è§£æ±ºãããŸããã
æšå¹Žã®è°è«ä»¥æ¥ã32ãããã§4ãã€ããè¶ ããæ§é äœã«å¯ŸããŠããè¯ãã³ãŒããçæããããšã«é¢ããJIT
ç§ã¯äœãç¥ããŸããã
@CyrusNajmabadiã®ææ¡ã«ã€ããŠã©ãæããŸãã
ãã¬ãŒã ã¯ãŒã¯ã¿ã€ãã¯ã95ïŒ ä»¥äžã®ã±ãŒã¹ã§ããŸãæ©èœããåçŽãªéžæã§ããå¿ èŠããããŸãã ãããã¯æéã®ãã®ã§ã¯ãªããããããŸããããããã¯åé¡ãããŸããã Hash32ãšHash64ã®ã©ã¡ãããéžæããã®ã¯ç°¡åãªéžæã§ã¯ãããŸããã
ããã¯ç§ã«ãšã£ãŠã¯å€§äžå€«ã§ãã ããããå°ãªããšããããã®95ïŒ ã®ã±ãŒã¹ã«å¯ŸããŠååãªè§£æ±ºçãåŸãããšãã§ããŸããïŒ ä»ã¯äœããããŸãã...ïŒ-/
hashCode = hashCode * -1521134295 + EqualityComparer
.Default.GetHashCodeïŒthis.sïŒ;
@CyrusNajmabadiãªãthis.s.GetHashCodeïŒïŒã ãã§ãªããããã§EqualityComparerãåŒã³åºããŠããã®ã§ããïŒ
éæ§é äœã®å ŽåïŒnullããã§ãã¯ããå¿ èŠããªãããã«ããŸãã
ããã¯ãèå°è£ã§ãå¿ååã«å¯ŸããŠçæãããã®ã«è¿ããã®ã§ãã æ¢ç¥ã®null以å€ã®å€ã®å Žåãæé©åããŠããŠãŒã¶ãŒã«ãšã£ãŠããå¿«é©ãªã³ãŒããçæããŸãã ãã ãããã®ããã®APIãçµã¿èŸŒãŸããŠãããšäŸ¿å©ã§ãã
EqualityComparer.Default.GetHashCodeã®åŒã³åºãã¯ãnullããã§ãã¯ããããã10å以äžé«äŸ¡ã§ãã
EqualityComparer.Default.GetHashCodeã®åŒã³åºãã¯ãnullããã§ãã¯ããããã10å以äžã³ã¹ããããããŸãã
åé¡ã®ããã«èãããŸãã è¯ãããã·ã¥ã³ãŒãAPIãããã°ãFxã§åŒã³åºãããšãã§ããŸã:)
ïŒãŸããå¿ååã§ããã®åé¡ãçºçããŸããããã¯ãããã§çæããããã®ã§ãããããã§ãïŒã
ã¿ãã«ã«å¯ŸããŠäœããããã¯ããããŸãããã䌌ãŠãããšæããŸãã
ã¿ãã«ã«å¯ŸããŠäœããããã¯ããããŸãããã䌌ãŠãããšæããŸãã
System.Tuple
ã¯ãæŽå²çãªçç±ã§EqualityComparer<Object>.Default
ãééããŸãã System.ValueTuple
ã¯ãnullãã§ãã¯ã䜿çšããŠObject.GetHashCodeãåŒã³åºããŸã-https ïŒ//github.com/dotnet/coreclr/blob/master/src/mscorlib/shared/System/ValueTuple.cs#L809ã
倧éã ã¿ãã«ã¯ãHashHelpersãã䜿çšã§ããããã§ãã ãŠãŒã¶ãŒãåãå©çãåŸãããšãã§ããããã«ããããå ¬éããããšã¯ã§ããŸããïŒ
çŽ æŽãããã ç§ã¯åããããªããšãããŠããããã§ãã å¿åã¿ã€ãããå§ããã®ã¯ããããã劥åœãªãã¹ããã©ã¯ãã£ã¹ã§ãããšèããããã§ãã ããã§ãªãå Žåã¯ãããã§åé¡ãããŸããã :)
ããããããã¯ç§ãããã«ããçç±ã§ã¯ãããŸããã ç§ã¯å®éã«ããã·ã¥ãå¹æçã«çµã¿åãããã·ã¹ãã ãæã«å ¥ããããã«ããã«ããŸãã ãããæäŸã§ããå Žåã¯ãä¹±æ°ãããŒãã³ãŒãã£ã³ã°ããŠããã·ã¥å€ãèªåã§çµã¿åãããã®ã§ã¯ãªããåãã§ãã®åŒã³åºãã«ç§»ããŸãã
ã³ã³ãã€ã©ãŒãçæããã³ãŒãã«æé©ã ãšæãAPIã®åœ¢ã¯äœã§ããããïŒ
æåéãã以åã«æ瀺ããã32ããããœãªã¥ãŒã·ã§ã³ã®ããããç§ã«ã¯åé¡ãããŸããã ã¡ãªã¿ã«ã64ããããœãªã¥ãŒã·ã§ã³ã¯ç§ã«ã¯åé¡ãããŸããã ãããã·ã¥ãããçš®ã®åççãªæ¹æ³ã§çµã¿åãããŠãåççã«åæ£ãããçµæãçæã§ããããšãããååŸã§ããAPIã®äžçš®ã§ãã
ç§ã¯ãããã®ã¹ããŒãã¡ã³ãã調æŽããããšã¯ã§ããŸããïŒ
ãµã€ãºã4ãã€ãã®äžå€ã®HashCodeæ§é äœããããŸããã æäŸãããããã·ã¥ã³ãŒããDJBX33Xã®ãããªã¢ã«ãŽãªãºã ãä»ããŠç¬èªã®ããã·ã¥ã³ãŒããšæ··åããæ°ããHashCodeãè¿ãCombineïŒintïŒã¡ãœããããããŸããã
@jkotasã¯ãDJBX33Xã®ãããªã¢ã«ãŽãªãºã ãååã«å ç¢ã§ãããšã¯èããŠããŸããã§ããã
ãš
ãã¬ãŒã ã¯ãŒã¯ã¿ã€ãã¯ã95ïŒ ä»¥äžã®ã±ãŒã¹ã§ããŸãæ©èœããåçŽãªéžæã§ããå¿ èŠããããŸãã
95ïŒ ã®ã±ãŒã¹ã§ååã«æ©èœããåçŽãª32ãããã®çŽ¯ç©ããã·ã¥ãæãä»ãããšãã§ããŸãããïŒ ããã§ããŸãåŠçãããŠããªãã±ãŒã¹ã¯äœã§ããããããŠãªããããã95ïŒ ã®ã±ãŒã¹ã«ãããšæããŸããïŒ
@jkotas ãããã©ãŒãã³ã¹ã¯ãã®ã¿ã€ãã«ãšã£ãŠæ¬åœã«éèŠã§ããïŒ å¹³åããŠãããã·ã¥ããŒãã«ã«ãã¯ã¢ããã®ãããªãã®ã§ãããããã¯ããã€ãã®æ§é äœã³ããŒãããã¯ããã«æéãããããšæããŸãã ããã«ããã¯ã§ããããšãå€æããå Žåã¯ãAPIã®ãªãªãŒã¹åŸã«32ãããã®æ§é äœã³ããŒãæé©åããããJITããŒã ã«äŸé ŒããŠãæé©åã«åãçµãã§ãã人ãããªããšãã«ãã®APIããããã¯ããã®ã§ã¯ãªããäœããã®ã€ã³ã»ã³ãã£ããåŸãã®ã劥åœã§ãããããã³ããŒïŒ
95ïŒ ã®ã±ãŒã¹ã§ååã«æ©èœããåçŽãª32ãããã®çŽ¯ç©ããã·ã¥ãæãä»ãããšãã§ããŸãããïŒ
ããã©ã«ãã§ã¯ãæååã®32ããã环ç©ããã·ã¥ãéåžžã«ã²ã©ãçŒãããŠããŸãããã®ããã.NETCoreã®æååã®Marvinããã·ã¥-httpsïŒ//github.com/dotnet/corert/blob/87e58839d6629b5f90777f886a2f52d7a99c076f/src/System.Private.CoreLib/ src / System / Marvin.csïŒL25ã ããã§åãéã¡ãç¹°ãè¿ããããªããšæããŸãã
@jkotas ãããã©ãŒãã³ã¹ã¯ãã®ã¿ã€ãã«ãšã£ãŠæ¬åœã«éèŠã§ããïŒ
ããã©ãŒãã³ã¹ã¯éèŠã§ã¯ãªããšæããŸãã ãã®APIã¯èªåçæãããã³ã³ãã€ã©ã³ãŒãã§äœ¿çšãããããã«èŠããã®ã§ãèŠãç®ãããå°ããçæã³ãŒããåªå ããå¿ èŠããããšæããŸãã éæµæ¢ãªãã¿ãŒã³ã¯ããå°ããªã³ãŒãã§ãã
æååã®ããã·ã¥ã环ç©ããããã©ã«ãã®32ãããã¯æ¬åœã«ã²ã©ãçŒãããŠããŸã
ããã¯95ïŒ ã®å Žåã®ããã«ã¯æããŸããã ç§ãã¡ã¯éåžžã®éçºè ããä»æ¥æåã§ç©äºãè¡ããã¹ãŠã®ã¿ã€ãã«ãååã«è¯ããããã·ã¥ãæãã§ããããšã«ã€ããŠè©±ããŠããã
ãã®APIã¯èªåçæãããã³ã³ãã€ã©ã³ãŒãã§äœ¿çšãããããã«èŠããã®ã§ãèŠãç®ãããå°ããçæã³ãŒããåªå ããå¿ èŠããããšæããŸãã éæµæ¢ãªãã¿ãŒã³ã¯ããå°ããªã³ãŒãã§ãã
ããã¯Roslynã³ã³ãã€ã©ã§ã¯äœ¿çšã§ããŸããã ããã¯ããŠãŒã¶ãŒãã¿ã€ãã®GetHashCodesãçæããã®ãæ¯æŽãããšãã«RoslynIDEã䜿çšããããã®ãã®ã§ãã ããã¯ããŠãŒã¶ãŒã衚瀺ããŠç¶æããå¿ èŠã®ããã³ãŒãã§ããã次ã®ãããªè³¢æãªãã®ããããŸãã
`` `cïŒ
Hash.CombineïŒthis.AïŒ.GetHashCodeïŒïŒ?? 0ã
this.BïŒ.GetHashCodeïŒïŒ?? 0ã
this.CïŒ.GetHashCodeïŒïŒ?? 0ïŒ;
is a lot nicer than a user seeing and having to maintain:
```c#
var hashCode = -1923861349;
hashCode = hashCode * -1521134295 + this.b.GetHashCode();
hashCode = hashCode * -1521134295 + this.i.GetHashCode();
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(this.s);
return hashCode;
ã€ãŸããFxã«ã¯ãã§ã«ãã®ã³ãŒãããããŸãã
ã¿ãã«ã«ã¯ååã ãšæããŸãã èªåã®ã¿ã€ãã§å©çšã§ããããã«ããããšããªããããªã«åé¡ã«ãªãã®ããç§ã«ã¯ããããŸããã
泚ïŒãããroslynã§è¡ãããšãæ€èšããŸããã
c#
return (this.A, this.B, this.C).GetHashCode();
ãããä»ãããªãã¯äººã ã«ãããçš®ã®åççãªããã©ã«ãã®ããã·ã¥åäœãåŸãããã ãã«ïŒæœåšçã«å€§ããªïŒæ§é äœãçæããããã«åŒ·å¶ããŠããŸãã
ç§ãã¡ã¯éåžžã®éçºè ããä»æ¥æåã§ç©äºãè¡ããã¹ãŠã®ã¿ã€ãã«ãååã«è¯ããããã·ã¥ãæãã§ããããšã«ã€ããŠè©±ããŠããã
å ã®æååããã·ã¥ã¯ãéåžžã®éçºè ã«ãšã£ãŠããŸãæ©èœãããååã«è¯ããããã·ã¥ã§ããã ããããASP.NET WebãµãŒããŒã¯ãåä¿¡ãããã®ãããã·ã¥ããŒãã«ã«ä¿åããåŸåããããããDoSæ»æã«å¯ŸããŠè匱ã§ããããšãçºèŠãããŸããã ãããã£ãŠããååã«è¯ããããã·ã¥ã¯åºæ¬çã«æªãã»ãã¥ãªãã£åé¡ã«ãªããŸããã
ã¿ãã«ã«ã¯ååã ãšæããŸã
å¿ ããããããšã¯éããŸããã ã¿ãã«ã®ããã¯ã¹ããã枬å®ãè¡ããããã·ã¥ã³ãŒããã©ã³ãã åããŠãåŸã§ã¢ã«ãŽãªãºã ãå€æŽãããªãã·ã§ã³ãæäŸããŸããã
return Hash.Combine(this.A?.GetHashCode() ?? 0, this.B?.GetHashCode() ?? 0, this.C?.GetHashCode() ?? 0);
ããã¯ç§ã«ã¯åççã«èŠããŸãã
ç§ã¯ããªãã®ããžãã€ã³ãååŸããŸããã ããªãã¯2ã€ã®ããšãèšã£ãŠããããã§ãïŒ
å ã®æååããã·ã¥ã¯ãéåžžã®éçºè ã«ãšã£ãŠããŸãæ©èœãããååã«è¯ããããã·ã¥ã§ããã ããããASP.NET WebãµãŒããŒã¯ãåä¿¡ãããã®ãããã·ã¥ããŒãã«ã«ä¿åããåŸåããããããDoSæ»æã«å¯ŸããŠè匱ã§ããããšãçºèŠãããŸããã ãããã£ãŠããååã«è¯ããããã·ã¥ã¯åºæ¬çã«æªãã»ãã¥ãªãã£åé¡ã«ãªããŸããã
ãã®å Žåã¯ãã»ãã¥ãªãã£ãDoSã«æžå¿µããã人ã«é©ããããã·ã¥ã³ãŒããæäŸããŸãããã
ãã¬ãŒã ã¯ãŒã¯ã¿ã€ãã¯ã95ïŒ ä»¥äžã®ã±ãŒã¹ã§ããŸãæ©èœããåçŽãªéžæã§ããå¿ èŠããããŸãã
ãã®å Žåã¯ã95ïŒ ã®ã±ãŒã¹ã«ååãªããã·ã¥ã³ãŒããæäŸããŸãããã ã»ãã¥ãªãã£/ DoSã«æžå¿µããã人ã¯ããã®ç®çã®ããã«ææžåãããå°çšã®ãã©ãŒã ã䜿çšã§ããŸãã
å¿ ããããããšã¯éããŸããã ã¿ãã«ã®ããã¯ã¹ããã枬å®ãè¡ããããã·ã¥ã³ãŒããã©ã³ãã åããŠãåŸã§ã¢ã«ãŽãªãºã ãå€æŽãããªãã·ã§ã³ãæäŸããŸããã
Okã ãŠãŒã¶ãŒãåãã¡ã«ããºã ã䜿çšã§ããããã«ããããå ¬éã§ããŸããïŒ
-
ãæ®éçãªè§£æ±ºçãäœãããšãã§ããªãã®ã§ã誰ããèªåã§è§£æ±ºããªããã°ãªããªãããšèšã£ãŠããããã«èãããã®ã§ãç§ã¯ããã§æ¬åœã«èŠåŽããŠããŸãã ããã¯ãææªã®å Žæã®1ã€ã«æããŸãã確ãã«ãã»ãšãã©ã®ã客æ§ã¯ãDoSã®æžå¿µã®ããã«ç¬èªã®ãããŒãã³ããã·ã¥ããäœæããããšãèããŠããªãããã§ãã ãããã¯ããã£ãŒã«ãããã·ã¥ã1ã€ã®æçµããã·ã¥ã«è¿œå ãæä»çè«çåããŸãã¯ãã®ä»ã®æ¹æ³ã§ããŸãçµã¿åãããŠããªãã ãã§ãã
95ïŒ ã®ã±ãŒã¹ãæ°ã«ããå Žåã¯ãäžè¬çã«åªããenoghããã·ã¥ãäœæããå¿ èŠããããŸãã 5ïŒ ã®ã±ãŒã¹ãæ°ã«ããå Žåã¯ããã®ããã®ç¹å¥ãªãœãªã¥ãŒã·ã§ã³ãæäŸã§ããŸãã
ããã¯ç§ã«ã¯åççã«èŠããŸãã
ãã°ããã:)次ã«å ¬éã§ããŸããïŒ
`` `cïŒ
åå空éSystem.Numerics.Hashing
{{
å
éšéçã¯ã©ã¹HashHelpers
{{
public static readonly int RandomSeed = new RandomïŒïŒãNextïŒInt32.MinValueãInt32.MaxValueïŒ;
public static int Combine(int h1, int h2)
{
// RyuJIT optimizes this to use the ROL instruction
// Related GitHub pull request: dotnet/coreclr#1830
uint rol5 = ((uint)h1 << 5) | ((uint)h1 >> 27);
return ((int)rol5 + h1) ^ h2;
}
}
Roslyn could then generate:
```c#
return Hash.Combine(Hash.RandomSeed,
this.A?.GetHashCode() ?? 0,
this.B?.GetHashCode() ?? 0,
this.C?.GetHashCode() ?? 0);
ããã«ã¯ãã»ãšãã©ã®å Žåã«å®éã«ãååã«è¯ãããšããå©ç¹ããããŸãããã©ã³ãã ã§ãªãããã·ã¥ã«äŸåããªãããã«ãã©ã³ãã ãªå€ã§åæåãããšããè¯ãéã人ã ã«å°ããŸãã
ã»ãã¥ãªãã£/ DoSã«æžå¿µããã人ã¯ããã®ç®çã®ããã«ææžåãããå°çšã®ãã©ãŒã ã䜿çšã§ããŸãã
ãã¹ãŠã®ASP.NETã¢ããªã«ã¯ãã»ãã¥ãªãã£/ DoSã®æžå¿µããããŸãã
ãã°ããã:)次ã«å ¬éã§ããŸããïŒ
ããã¯ç§ãåççã ãšèšã£ãããšãšã¯ç°ãªããŸãã
https://github.com/aspnet/Common/blob/dev/shared/Microsoft.Extensions.HashCodeCombiner.Sources/HashCodeCombiner.csã«ã€ããŠã©ãæããŸããã ããã¯ãASP.NETã®å éšã§ä»æ¥å€ãã®å Žæã§äœ¿çšãããŠãããã®ã§ãããç§ãéåžžã«æºè¶³ããŠãããã®ã§ãïŒãã ããçµåé¢æ°ããã匷åã«ããå¿ èŠããããŸããå®è£ ã®è©³çŽ°ã調æŽãç¶ããããšãã§ããŸãïŒã
@jkotasèãããïŒp
ãããã£ãŠãããã§ã®åé¡ã¯ãéçºè ãDoSæ»æã®åœ±é¿ãåããããææãããããªãããšã§ããããã¯ãéçºè ãããã«ã€ããŠäœãèããŠããªãããã§ãããã®ãããMarvin32ã䜿çšããããã«æååãåãæ¿ããŸããã
ããã蚌æããæ¹æ³ããªãã®ã§ãã95ïŒ ã®ã±ãŒã¹ã¯åé¡ã§ã¯ãªãããšããéãé²ãã¹ãã§ã¯ãããŸãããããã©ãŒãã³ã¹ã³ã¹ãããã£ãŠãã泚æãæ ãå¿ èŠããããŸãã ããããé¢ããå Žåã¯ãããã·ã¥ã³ãŒãã®å®è£ ã«ã¯ããããã§ååã ããšå€æããã ãã§ãªããæå·åããŒãã®ã¬ãã¥ãŒãå¿ èŠã§ãã
ãã¹ãŠã®ASP.NETã¢ããªã«ã¯ãã»ãã¥ãªãã£/ DoSã®æžå¿µããããŸãã
Okã ã§ã¯ãä»æ¥ã誰ãããã·ã¥ã³ãŒãã®å©ããåããŠããªããããããŸãæ©èœããŠããªãå¯èœæ§ããããšããåé¡ã«ã©ã®ããã«å¯ŸåŠããŠããŸããïŒ æããã«ããã®ãããªäžçã®ç¶æ ãæã€ããšã¯å®¹èªãããŠããŸãã ã§ã¯ãä»æ¥äººã ãæã§è»¢ãããŠãããã®ãããããã©ãŒãã³ã¹ãåªããŠãããšæãããåççãªããã·ã¥ã·ã¹ãã ãæäŸããããšã«ãã£ãŠäœã害ãããã®ã§ããããã
ããã蚌æããæ¹æ³ããªãã®ã§ãããã©ãŒãã³ã¹ãç ç²ã«ãªã£ããšããŠãã泚æãæ ããªããã°ãªããŸããã
ããªããäœããæäŸããªããã°ã人ã ã¯ãã ã²ã©ãããšããç¶ããã§ãããã å®ç§ãªãã®ãäœããªããšããçç±ã§ãååã«è¯ãããæåŠããããšã¯ãä»æ¥ã®çŸç¶ãæªãããšãæå³ããŸãã
ãã¹ãŠã®ASP.NETã¢ããªã«ã¯ãã»ãã¥ãªãã£/ DoSã®æžå¿µããããŸãã
ããã説æã§ããŸããïŒ ç§ãç解ããŠããããã«ãä»»æã®å ¥åãåãå ¥ããŠãå ¥åãç¹å¥ã«çŽ°å·¥ã§ããå Žåã¯ããã©ãŒãã³ã¹ãäœäžããããŒã¿æ§é ã«ãããæ ŒçŽããå ŽåãDoSã®æžå¿µããããŸãã ããããŸãããããããŠãŒã¶ãŒããæ¥ãWebã·ããªãªã§ååŸããæååã«é¢ããæžå¿µäºé ã§ããããšãããããŸããã
ã§ã¯ããã®ã·ããªãªã§äœ¿çšãããŠããªãæ®ãã®ã¿ã€ãã«ã©ã®ããã«é©çšãããã®ã§ããããã
次ã®ã¿ã€ãã®ã»ããããããŸãã
åºæ¬çã«ããããã®ã±ãŒã¹ã¯éèŠã§ãããšèããŠããŸãããã1ããŸãã¯ã2ããåŠçãããœãªã¥ãŒã·ã§ã³ããŠãŒã¶ãŒã«å®éã«æäŸããã«ã¯ååã§ã¯ãããŸããã ã2ãã®è§£æ±ºçãã1ãã«é©ããªãã®ã§ã¯ãªãããšå¿é ããŠããã®ã§ããããããããæäŸããããšããããŸããã ãããŠãã1ãã®è§£æ±ºçãæäŸããæ°ãããªããã°ãç§ãã¡ã¯ä¿¡ããããªãã»ã©å¥åŠãªç«å Žã«ããããã«æããŸãã ç§ãã¡ã¯DoSingãšASPã«ã€ããŠå¿é ããŠããŸãããå®éã«äººã ãå©ããããã«å¿é ããŠããŸããã ãããŠãç§ãã¡ã¯ããã§äººã ãå©ããªãã®ã§ãDoS以å€ã®ã±ãŒã¹ã§ãããå©ããã€ãããããããŸããã
-
ãããã®2ã€ã®ã±ãŒã¹ãéèŠã§ããå ŽåïŒç§ã¯ãããåãå ¥ããŠãæ§ããªããšæã£ãŠããŸãïŒã2ã€ã®APIãæäŸããªãã®ã¯ãªãã§ããïŒ ããããææžåããŸãã 圌ããäœã®ããã«ããã®ããæ確ã«ããŠãã ããã 人ã ãããããé©åã«äœ¿çšãããªãã°ãçŽ æŽãããã 人ã ãããããé©åã«äœ¿çšããªããŠããããã§ãåé¡ãããŸããã çµå±ã®ãšããã圌ãã¯ãšã«ããä»æ¥ã¯ç©äºãé©åã«è¡ã£ãŠããªãå¯èœæ§ãé«ãã®ã§ãç©äºã¯ã©ã®ããã«æªåããŠããŸããïŒ
ã«ã€ããŠã©ãæããŸãã
ç§ã¯ã©ã¡ãã®æ¹æ³ã§ãæèŠããããŸããã 顧客ã䜿çšã§ããAPIã§ããã蚱容ã§ããããã©ãŒãã³ã¹ãçºæ®ããæ確ãªã³ãŒããåããã·ã³ãã«ãªAPIãæäŸããã®ã§ããã°ãããã§åé¡ãªããšæããŸãã
ãã£ãŒã«ã/ããããã£ã®ã»ãããé åºä»ããããæ¹æ³ã§çµåããããšãã99ïŒ ã®ã±ãŒã¹ãåŠçãããåçŽãªéçãã©ãŒã ããããšäŸ¿å©ã ãšæããŸãã ãã®ãããªãã®ããã®ã¿ã€ãã«ããªãç°¡åã«è¿œå ã§ããããã§ãã
ã·ã³ãã«ãªéçãªåœ¢ãããã°ãããšæããŸã
åæã
ãã£ãŒã«ã/ããããã£ã®ã»ãããé åºä»ããããæ¹æ³ã§çµåããããšãã99ïŒ ã®ã±ãŒã¹ãåŠçãããåçŽãªéçãã©ãŒã ããããšäŸ¿å©ã ãšæããŸãã ãã®ãããªãã®ããã®ã¿ã€ãã«ããªãç°¡åã«è¿œå ã§ããããã§ãã
åæã
ããçš®ã®APIãå®çŸããã®ãæ¬åœã«èŠããã®ã§ãããã«ã€ããŠã¯éäžã§ãäŒãããŸãããã @jkotasäžå€ã®ã€ã³ã¹ã¿ã³ã¹ããŒã¹ã®APIãè¿œå ããããšã«å察ããŠããããšãç§ã¯ãŸã ç解ããŠããŸããã æåã«ã32ãããã³ããŒãé
ãããã ãšèšããŸããã次ã«ãå¯å€APIãããç°¡æœã«ãªãããã§ãïŒããã¯æ£ãããããŸããã h.Combine(a).Combine(b)
ïŒäžå€ããŒãžã§ã³ïŒã¯h.Combine(a); h.Combine(b);
ïŒå¯å€ããŒãžã§ã³ïŒãããçãã§ãïŒããŒãžã§ã³ïŒïŒã
ããã¯èšã£ãŠããç§ã¯æ»ã£ãŠåãã§ïŒ
public static class HashCode
{
public static int Combine<T>(T value1, Tvalue2);
public static int Combine<T>(T value1, Tvalue2, IEqualityComparer<T> comparer);
public static int Combine<T>(T value1, Tvalue2, T value3);
public static int Combine<T>(T value1, Tvalue2, T value3, IEqualityComparer<T> comparer);
public static int Combine<T>(T value1, Tvalue2, T value3, T value4);
public static int Combine<T>(T value1, Tvalue2, T value3, T value4, IEqualityComparer<T> comparer);
// ... All the way until value8
}
ããã¯åççã ãšæããŸããïŒ
çŸåšãæçš¿ãç·šéããããšã¯ã§ããŸãããããã¹ãŠã®ã¡ãœãããTãåãå ¥ããããšãã§ããããã§ã¯ãªãããšã«æ°ä»ããŸããããã®å Žåããã¹ãŠã®intãåãå ¥ãã8ã€ã®ãªãŒããŒããŒããããããŠãŒã¶ãŒã«GetHashCodeãåŒã³åºãããããšãã§ããŸãã
ãããã®2ã€ã®ã±ãŒã¹ãéèŠã§ããå ŽåïŒç§ã¯ãããåãå ¥ããŠãæ§ããªããšæã£ãŠããŸãïŒã2ã€ã®APIãæäŸããªãã®ã¯ãªãã§ããïŒ ããããææžåããŸãã 圌ããäœã®ããã«ããã®ããæ確ã«ããŠãã ããã 人ã ãããããé©åã«äœ¿çšããã°ãçŽ æŽãããã 人ã ãããããé©åã«äœ¿çšããªããŠããããã§ãåé¡ãããŸããã çµå±ã®ãšããã圌ãã¯ãšã«ããä»æ¥ã¯ç©äºãé©åã«è¡ã£ãŠããªãå¯èœæ§ãé«ãã®ã§ãç¶æ³ã¯ã©ã®ããã«æªåããŠããŸããïŒ
圌ããããã«ãããšãã人ã ã¯ç©äºãé©åã«äœ¿çšããªãããã§ãã ç°¡åãªäŸãXSSãèŠãŠã¿ãŸãããã æåãããWebãã©ãŒã ã§ããåºåãHTMLãšã³ã³ãŒãããæ©èœããããŸããã ãã ããéçºè ã¯ãªã¹ã¯ãç¥ãããé©åã«è¡ãæ¹æ³ãç¥ãããæé ãã«ãªã£ããšãã«ã®ã¿ã¢ããªãå ¬éãããèªèšŒCookieã解é€ãããŸããã
人ã ã«ã»ãã¥ãªãã£ã®éžæãäžããããšã¯ã圌ãã圌ããåæãšããŠããŸã
ãããã®ä»®å®ã¯ãäžè¬çã«å€§å€æ°ã®éçºè ã«ã¯åœãŠã¯ãŸããŸããã圌ãã¯ãæé ãã«ãªã£ããšãã«ã®ã¿åé¡ãèŠã€ããŸãã éçºè ã¯ã»ãã¥ãªãã£äŒè°ã«åå ããããã¯ã€ãããŒããŒãèªãã ãããœãªã¥ãŒã·ã§ã³ãç解ãããããŸããã ãã®ãããASP.NET HashDoSã·ããªãªã§ã¯ãããããéžæããŸãããããã¯æ£ããããšã§ãããæ倧ã®åœ±é¿ãäžãããããããã©ã«ãã§ä¿è·ããŸããã ãããããããæååã«ã®ã¿é©çšããããããŠãŒã¶ãŒå ¥åããã«ã¹ã¿ã ã¯ã©ã¹ãæ§ç¯ããŠãã人ã ã¯æªãå Žæã«çœ®ãããŸããã ç§ãã¡ã¯æ£ããããšãããä»ãããããã®é¡§å®¢ãä¿è·ãããããããã©ã«ãã«ããŠã倱æã§ã¯ãªãæåã®èœãšãç©Žãæãããå¿ èŠããããŸãã ã»ãã¥ãªãã£ã®ããã®APIèšèšã¯ãéžæã§ã¯ãªãããŠãŒã¶ãŒããããç¥ã£ãŠãããã©ããã«é¢ä¿ãªãæ¯æŽããããšãç®çãšããŠããå ŽåããããŸãã
ãŠãŒã¶ãŒã¯ãã€ã§ãã»ãã¥ãªãã£ã«çŠç¹ãåœãŠãŠããªãããã·ã¥ãäœæã§ããŸãã ãããã£ãŠã2ã€ã®ãªãã·ã§ã³ãäžããããŸã
次ã«ã2çªç®ã®æ¹ãããããåªããŠããŸãã ãããŠãææ¡ãããŠããããšã¯ãæå·åããã·ã¥ã«å¯Ÿãããã«ã®ããã©ãŒãã³ã¹ãžã®åœ±é¿ã¯ãããŸããã ã ããããã¯è¯ã劥åç¹ã«ãªããŸããïŒ
ãããã®ã¹ã¬ããã§å®è¡ãããŠãã質åã®1ã€ã¯ãã©ã®ã¢ã«ãŽãªãºã ããã¹ãŠã®äººã«æé©ããšããããšã§ãã å®ç§ãªã¢ã«ãŽãªãºã ã¯1ã€ããªããšèšã£ãŠãéèšã§ã¯ãããŸããã ãã ãã @ CyrusNajmabadiã瀺ããŠãããããªãäžè¬çãª.NETå ¥åã®ãšã³ããããŒãäžååãªåŸåãããã³ãŒãããã®ä»ã®äžè¬çãªããã·ã£ãŒãã°ïŒå ¥åããŒã¿ã®æ倱ãç°¡åãªãã®ãªã©ïŒãããåªããã³ãŒããæäŸããããšã
ãæè¯ã®ã¢ã«ãŽãªãºã ãã®åé¡ãåé¿ããããã®ããã€ãã®ãªãã·ã§ã³ãææ¡ããããšæããŸãã
Marvin32.Create();
çæãããšããã¯ãŒãŠãŒã¶ãŒã¯ãããäœãããããšã«æ±ºããããç¥ãããšãã§ããå¿
èŠã«å¿ããŠã¹ã€ãŒãå
ã®å¥ã®ã¢ã«ãŽãªãºã ã«ç°¡åã«å€æŽã§ããŸããCC @ bartonjs ã @ terrajobst
@morganbrå®ç§ãªã¢ã«ãŽãªãºã ã¯1ã«å ããŠãé«åºŠãªäœ¿çšã®ããã®äžé£ã®ã¢ã«ãŽãªãºã Dictionary
å
¥ããããã«ãããŒãŽã£ã³ã誰ã§ããããç¥ãå¿
èŠã¯ãããŸããã
ãªããžã§ã¯ããèŸæžã«å ¥ããããã«ãããŒãŽã£ã³ã誰ã§ããããç¥ãå¿ èŠã¯ãããŸããã
ç§ã¯ããªããããã眮ãæ¹æ³ã奜ãã§ãã ç§ã¯ããªããèŸæžèªäœã«ã€ããŠèšåããããšã奜ãã§ãã IDictionaryã¯ãããããçš®é¡ã®ç°ãªãå質ãæã€å€æ°ã®ç°ãªãimplãæã€ããšãã§ãããã®ã§ãïŒå€ãã®ãã©ãããã©ãŒã ã®ã³ã¬ã¯ã·ã§ã³APIãåç §ããŠãã ããïŒã ãã ãããã¹ãŠã®ã«ããŽãªã§åªããŠãããšã¯éããŸããããå šäœçã«ãŸãšããªä»äºãããããŒã¹ã®ãèŸæžããæäŸããã ãã§ãã
ç§ã¯ããã人ã ã®ãã³ã¯ãããã·ã¥ã©ã€ãã©ãªã§æ¢ããŠãããã®ã ãšæããŸãã ããšãããããã¹ãŠã®ç®çã«å®ç§ã§ãªããŠããä»äºãæãéããäœãã
@morganbr人ã ã¯åçŽã«ãä»æ¥è¡ã£ãŠããããšãããåªããGetHashCodeãäœæããæ¹æ³ãæãã§ãããšæããŸãïŒéåžžãWebäžã®äœãããã³ããŒããæ°åŠæŒç®ã®ããã€ãã®ã°ã©ãããã°ã®çµã¿åããïŒã ããŸãæ©èœããåºæ¬çãªå®è£ ãæäŸã§ããã°ã人ã ã¯å¹žãã«ãªããŸãã ç¹å®ã®ããã·ã¥é¢æ°ã匷ãå¿ èŠãªå Žåã¯ãäžçŽãŠãŒã¶ãŒåãã®èå°è£APIã䜿çšã§ããŸãã
èšãæããã°ãä»æ¥ããã·ã¥ã³ãŒããæžããŠãã人ã ã¯ããªã圌ããäžæ°å³ãªå¯ŸããŒãŽã£ã³å¯Ÿã€ã¶ããã欲ããã®ããç¥ããæ°ã«ãããªãã§ãããã ãããã®ç¹å®ã®ããã·ã¥ã³ãŒãã®1ã€ãç¹ã«å¿ èŠãšããŠãã人ã ããæ¢ãã«è¡ããŸãã ããããå€ãã®äººã¯ããããç§ã®ãªããžã§ã¯ãã®ç¶æ ã§ããèŸæžã§äœ¿çšã§ããé«éãªåæ£ããã·ã¥ãçæããæ¹æ³ãæäŸããŠãããŸããããã«ãããçºçããå Žåã«DOSãå®è¡ãããªããªããšæããŸããä¿¡é Œã§ããªãå ¥åãååŸããŠããã·ã¥ããä¿åããŸããã
@CyrusNajmabadiåé¡ã¯ãçŸåšã®äºææ§ã®æŠå¿µãå°æ¥ã«æ¡åŒµãããšããã®ã¿ã€ããåºè·ããããšå€æŽã§ããªãããšããããããšã§ãïŒã¢ã«ãŽãªãºã ãããã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ãæ»æå¯èœã«ãããæ¹æ³ã§ã²ã©ãå£ããŠããããšãããã£ãå Žåãé€ãïŒ ïŒã
ãšã«ããå®è¡ããšã«å€ã«äŸåããããšãã§ããªãã£ãã®ã§ããããå®å®ããã©ã³ãã åãããæ¹æ³ãšããŠéå§ãããå Žåãå®è£
ãå€æŽããã®ãç°¡åã«ãªããšäžåºŠäž»åŒµããããšãã§ããŸãã ããããæ°å¹ŽåŸãããã·ã¥ãã±ãããšäžè¬çãªã±ãŒã¹ã®ããã©ãŒãã³ã¹ã®ãã©ã³ã¹ããšãã®ã«ããªã¹ããå«ãæ§é ãäœæããã¢ã«ãŽãªãºã ãããããšãããããŸããã ã¢ãŒã¬ã³ã®ææ¡ã§ã¯ãä»æ¥äœæããã³ãŒãã¯ãäºå®äžãæ°žä¹
ã«åãããã©ãŒãã³ã¹ç¹æ§ãæã€ããšã«ãªããŸãã è¯ããªã£ããããããªãã¢ããªã±ãŒã·ã§ã³ã«ãšã£ãŠãããã¯æ®å¿µãªããšã§ãã æªåããã§ãããã¢ããªã±ãŒã·ã§ã³ã«ãšã£ãŠãããã¯çŽ æŽãããããšã§ãã ããããæ°ããã¢ã«ãŽãªãºã ãèŠã€ãã£ãããããããã§ãã¯ã€ã³ããRoslynãå€æŽããŠïŒãããŠReSharperãªã©ãžã®å€æŽãææ¡ããŠïŒââãSomeThingThatWasConsideredAwesomeIn2018ã§ã¯ãªãNewAwesomeThing2019ã§çæãéå§ããŸãã ãã®ãããªã¹ãŒããŒãã©ãã¯ããã¯ã¹ã¯ãäžåºŠããå®è¡ã§ããŸããã ãããŠãç§ãã¡ã¯æ°žé ã«ããã«åºå·ããŠããŸãã 次ã«ã誰ãã次ã®å®è£
ãäœæããŸããããã¯å¹³åããã©ãŒãã³ã¹ãåªããŠããããã2ã€ã®ãã©ãã¯ããã¯ã¹ã®å®è£
ããããã©ã¡ããéžæããã®ãããããŸããã ãããŠ...ãããŠ.... ãããã£ãŠã確ãã«ãRoslyn / ReSharper / etcãMarvin32ãMurmurãFastHashããŸãã¯IntPtr.Sizeã«åºã¥ãçµã¿åãã/æ¡ä»¶ä»ãã䜿çšããŠGetHashCodeãèªåæžã蟌ã¿ããçç±ãããããªãå ŽåããããŸãã ããããããªãã«ã¯ããã調ã¹ãåããããŸãã ãããŠãæ°ããæ
å ±ãæããã«ãªã£ããšãã«ãåŸã§ã¿ã€ããå€æŽããæš©éããããŸã...ããããåããŸãŸã«ããæš©éãäžããããŠããŸãã ïŒãããæžããšæ²ããã§ãããã3幎åŸãRoslyn / ReSharper / etcã¯ãæ°ããã¢ã«ãŽãªãºã ã®æ¹ãã¯ããã«åªããŠãããããæ瀺çã«åŒã³åºãããšãé¿ããŠããŸã...éåžžïŒã
@bartonjs .Netããã©ãã¯ããã¯ã¹ã¢ã«ãŽãªãºã ãŸãã¯ããŒã¿æ§é ãæäŸãããã¹ãŠã®å Žæãšããã·ã¥ãç°ãªãç¹ã¯äœã§ããïŒ ããšãã°ã䞊ã¹æ¿ãïŒã€ã³ãããœãŒãïŒã Dictionary
ïŒé
åããŒã¹ã®åå¥ã®ãã§ãŒã³ïŒã StringBuilder
ïŒ8kãã£ã³ã¯ã®ãªã³ã¯ãªã¹ãïŒãã»ãšãã©ã®LINQã
ä»æ¥ã¯ããã詳ããèŠãŠããŸããã ãã®åé¡ã«é¢ããé 延ãšååŸã®è¬çœªã
`` `CïŒ
//ã³ã¢ã¢ã»ã³ããªã«ååšããŸã
// .NET FrameworkïŒmscorlib
// .NET CoreïŒSystem.Runtime / System.Private.CoreLib
åå空éã·ã¹ãã
{{
public struct HashCode
{{
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public void Add<T>(T value);
public void Add<T>(T value, IEqualityComparer<T> comparer);
public void Add<T>(T[] value);
public void Add<T>(T[] value, int index, int length);
public void Add(byte[] value);
public void Add(byte[] value, int index, int length);
public void Add(string value);
public void Add(string value, StringComparison comparisonType);
public int ToHashCode();
}
}
Notes:
* We decided to not override `GetHashCode()` to produce the hash code as this would be weird, both naming-wise as well as from a behavioral standpoint (`GetHashCode()` should return the object's hash code, not the one being computed).
* We decided to use `Add` for the builder patter and `Combine` for the static construction
* We decided to use not provide a static initialization method. Instead, `Add` will do this on first use.
* The struct is mutable, which is unfortunate but we feel the best compromise between making `GetHashCode()` very cheap & not cause any allocations while allowing the structure to be bigger than 32-bit so that the hash code algorithm can use more bits during accumulation.
* `Combine` will just call `<value>.GetHashCode()`, so it has the behavior of the value's type `GetHashCode()` implementation
- For strings that means different casing will produce different hash codes
- For arrays, that means the hash code doesn't look at the contents but uses reference semantics for the hash code
- If that behavior is undesired, the developer needs to use the builder-style approach
### Usage
The simple case is when someone just wants to produce a good hash code for a given type, like so:
```C#
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public override int GetHashCode() => HashCode.Combine(Id, FirstName, LastName);
}
ããè€éãªã±ãŒã¹ã¯ãéçºè ãããã·ã¥ã®èšç®æ¹æ³ã埮調æŽããå¿ èŠãããå Žåã§ãã ã¢ã€ãã¢ã¯ã次ã®ããã«ãåŒã³åºããµã€ãããªããžã§ã¯ã/å€ã§ã¯ãªããç®çã®ããã·ã¥ãæž¡ããšãããã®ã§ãã
`` `CïŒ
ãããªãã¯ããŒã·ã£ã«ã¯ã©ã¹ã«ã¹ã¿ããŒ
{{
public override int GetHashCodeïŒïŒ=>
HashCode.CombineïŒ
Idã
StringComparer.OrdinalIgnoreCase.GetHashCodeïŒFirstNameïŒã
StringComparer.OrdinalIgnoreCase.GetHashCodeïŒLastNameïŒã
ïŒ;
}
And lastly, if the developer needs more flexibility, such as producing a hash code for more than eight values, we also provide a builder-style approach:
```C#
public partial class Customer
{
public override int GetHashCode()
{
var hashCode = new HashCode();
hashCode.Add(Id);
hashCode.Add(FirstName, StringComparison.OrdinalIgnoreCase);
hashCode.Add(LastName, StringComparison.OrdinalIgnoreCase);
return hashCode.ToHashCode();
}
}
ãã®åé¡ã¯åŒãç¶ã解決ãããŸãã APIãå®è£ ããã«ã¯ã䜿çšããã¢ã«ãŽãªãºã ã決å®ããå¿ èŠããããŸãã
@morganbrã¯è¯ãåè£è ã®ããã®ææ¡ãããŸãã äžè¬çã«èšã£ãŠãããã·ã¥ã¢ã«ãŽãªãºã ãæåããäœæããã®ã§ã¯ãªããããããã£ãããç解ãããŠããæåãªã¢ã«ãŽãªãºã ã䜿çšããŸãã
ãã ããäžè¬çãª.NETã¯ãŒã¯ããŒãã®å®è£ ã枬å®ããã©ã®ã¢ã«ãŽãªãºã ãè¯å¥œãªçµæïŒã¹ã«ãŒããããšåæ£ïŒãçæãããã確èªããå¿ èŠããããŸãã çãã¯CPUã¢ãŒããã¯ãã£ã«ãã£ãŠç°ãªãå¯èœæ§ãé«ãããã枬å®ããéã«ã¯ãããèæ ®ããå¿ èŠããããŸãã
@jamesqo ãããªãã¯ãŸã ãã®åéã§åãããšã«èå³ããããŸããïŒ ãã®å Žåã¯ãé©å®ææ¡ãæŽæ°ããŠãã ããã
@terrajobst ã public static int Combine<T1>(T1 value);
ãå¿
èŠãªå ŽåããããŸãã å°ãããããããã«èŠããããšã¯ç¥ã£ãŠããŸãããå
¥åããã·ã¥ã¹ããŒã¹ãéãããŠãããã®ããããããæ¡æ£ããæ¹æ³ãæäŸããŸãã ããšãã°ãå€ãã®åæåã«ã¯ãã³ãŒãã®äžäœæ°ãããã®ã¿ã䜿çšããŠãå¯èœãªããã·ã¥ãããã€ããããŸãã äžéšã®ã³ã¬ã¯ã·ã§ã³ã¯ãããã·ã¥ãããåºãã¹ããŒã¹ã«åæ£ããŠããããšãåæã«æ§ç¯ãããŠãããããããããæ¡æ£ãããšãã³ã¬ã¯ã·ã§ã³ãããå¹ççã«æ©èœããå ŽåããããŸãã
public void Add(string value, StrinComparison comparison);
NitïŒ StringComparison
ãã©ã¡ãŒã¿ãŒã®ååã¯comparisonType
ããŠãä»ã®å Žæã§äœ¿çšãããŠããååãšäžèŽãããå¿
èŠããããŸãããã以å€ã®å Žåã¯ã StringComparison
ããã©ã¡ãŒã¿ãŒãšããŠäœ¿çšãããŸãã
ã¢ã«ãŽãªãºã ã®éžæã«åœ¹ç«ã€åºæºã¯æ¬¡ã®ãšããã§ãã
ç§ãã¡ãæ¬åœã«æãã§ããã®ã¯ãCïŒã§èšè¿°ãããåè£è ã®ããã©ãŒãã³ã¹ã®æ°å€ã§ããããã«ãããåè£è ã®ç¹æ§ã.NETã§ãç¶æããããšåççã«ç¢ºä¿¡ã§ããŸãã ããªããåè£è ãæžããç§ãã¡ãããã®ããã«ãããéžã°ãªãå Žåãç§ãå®éã«éæå·åããã·ã¥APIã®APIææ¡ããŸãšãããšãã¯ãã€ã§ããããã¯ãŸã æçšãªä»äºã§ãã
è©äŸ¡ãã䟡å€ããããšæãåè£è ãããã€ã瀺ããŸãïŒãã ããä»ã®åè£è ãèªç±ã«ææ¡ããŠãã ããïŒã
æ¥Add
ã¡ãœããã¯æ»ãå€ã®åã¯ã§ããŸããref HashCode
ããŠè¿ãref this
圌ãã¯æµæ¢ãªæ¹æ³ã§äœ¿çšããããšãã§ããã®ã§ã
readonly ref
è¿åã§ãããå¯èœã«ãªããŸããïŒ / cc @jaredpar @VSadov
èŠåïŒã€ã³ã¿ãŒãããäžã®æ¢åã®ã³ãŒãããŒã¹ããããã·ã¥å®è£ ãéžæããå Žåã¯ããœãŒã¹ãžã®ãªã³ã¯ãä¿æããã©ã€ã»ã³ã¹ã確èªããŠãã ããïŒãããè¡ãå¿ èŠããããŸãïŒã
ã©ã€ã»ã³ã¹ã«äºææ§ããªãå Žåã¯ãã¢ã«ãŽãªãºã ãæåããäœæããå¿ èŠãããå ŽåããããŸãã
Addã¡ãœããã䜿çšããIMOã¯ãéåžžã«ãŸããªã¯ãã§ãã ããã¯éåžžã«é«åºŠãªã·ããªãªã®ããã®ãã®ã§ããããæµæ¢ãã§ããããšãã§ããå¿ èŠæ§ã¯å®éã«ã¯ãããŸããã
ãã¹ãŠã®ãŠãŒã¶ãŒã³ãŒãã±ãŒã¹ã®99ïŒ
ã®äžè¬çãªãŠãŒã¹ã±ãŒã¹ã§ã¯ã => HashCode.Combine(...)
ã䜿çšããŠåé¡ããªãã¯ãã§ãã
@morganbr
public static int Combine<T1>(T1 value);
ãå¿ èŠãªå ŽåããããŸãã å°ãããããããã«èŠããããšã¯ç¥ã£ãŠããŸãããå ¥åããã·ã¥ã¹ããŒã¹ãéãããŠãããã®ããããããæ¡æ£ããæ¹æ³ãæäŸããŸã
ãããã è¿œå ããŸããã
@justinvp
NitïŒ
StringComparison
ãã©ã¡ãŒã¿ãŒã®ååã¯comparisonType
ããŠãä»ã®å Žæã§äœ¿çšãããŠããååãšäžèŽãããå¿ èŠããããŸãããã以å€ã®å Žåã¯ãStringComparison
ããã©ã¡ãŒã¿ãŒãšããŠäœ¿çšãããŸãã
ä¿®çæžã¿ã
@CyrusNajmabadi
Add
ã¡ãœããã䜿çšããIMOã¯ãéåžžã«çããã¯ãã§ãã ããã¯éåžžã«é«åºŠãªã·ããªãªã®ããã®ãã®ã§ããããæµæ¢ãã§ããããšãã§ããå¿ èŠæ§ã¯å®éã«ã¯ãããŸããã
åæããŸããã
@benaadams -åïŒæ»ã£ãŠåç
§this
ããAdd
-ãããã this
ãããã¯å³èŸºå€ãŸãã¯TEMPããããšãã§ãããããæ§é äœã®ã¡ãœããã«åç
§ã«ãã£ãŠè¿ãããšã¯ã§ããŸããã
`` `CïŒ
ref var r =ïŒnew TïŒïŒïŒãReturnsRefThisïŒïŒ;
// rã¯ããã§ããã€ãã®å€æ°ãåç
§ããŸãã ã©ãïŒ ç¯å²/寿åœã¯ã©ã®ãããã§ããïŒ
r = SomethingElseïŒïŒ;
`` `
æ¯èŒã«åœ¹ç«ã€å Žåã®ããã«ãæ°å¹Žåã«Jenkinsã®lookup3ããã·ã¥é¢æ°ïŒ CãœãŒã¹ïŒãããã®CïŒã«ç§»æ€ã
ç§ã¯ã³ã¬ã¯ã·ã§ã³ã«ã€ããŠçåã«æã£ãŠããŸãïŒ
@terrajobst
c# public void Add<T>(T[] value);
é
åã«ã¯ãªãŒããŒããŒãããããŸãããäžè¬çãªã³ã¬ã¯ã·ã§ã³ïŒã€ãŸãã IEnumerable<T>
ïŒã«ã¯ãªãŒããŒããŒãããªãã®ã¯ãªãã§ããïŒ
ãŸãã HashCode.Combine(array)
ãšhashCode.Add((object)array)
ãäžæ¹åã«åäœãïŒåç
§ã®åçæ§ã䜿çšïŒã hashCode.Add(array)
ãå¥ã®æ¹åã«åäœããïŒå€ã®ããã·ã¥ã³ãŒããçµã¿åãããïŒããšã¯æ··ä¹±ããŸãããïŒé
åïŒïŒ
@CyrusNajmabadi
ãã¹ãŠã®ãŠãŒã¶ãŒã³ãŒãã±ãŒã¹ã®99ïŒ ã®äžè¬çãªãŠãŒã¹ã±ãŒã¹ã§ã¯ã
=> HashCode.Combine(...)
ã䜿çšããã ãã§åé¡ãªãã¯ãã§ãã
ç®çãå®éã«99ïŒ
ã®ãŠãŒã¹ã±ãŒã¹ã§Combine
ã䜿çšã§ããããã«ããããšã§ããå ŽåïŒããšãã°ã80ïŒ
ã§ã¯ãªãïŒã Combine
äœããã®æ¹æ³ã§å€ã«åºã¥ãããã·ã¥ã³ã¬ã¯ã·ã§ã³ããµããŒãããã¹ãã§ã¯ãããŸããã³ã¬ã¯ã·ã§ã³ã«ïŒ ãã¶ããããè¡ãå¥ã®ã¡ãœããïŒ HashCode
æ¡åŒµã¡ãœãããŸãã¯éçã¡ãœããã®ããããïŒãããã¯ãã§ããïŒ
Addã匷åãªã·ããªãªã§ããå ŽåããŠãŒã¶ãŒãObject.GetHashCodeãšã³ã¬ã¯ã·ã§ã³ã®åã
ã®èŠçŽ ã®çµã¿åããã®ã©ã¡ãããéžæããå¿
èŠããããšæ³å®ããå¿
èŠããããŸããïŒ ããã圹ç«ã€å Žåã¯ãé
åïŒããã³æœåšçãªIEnumerableïŒããŒãžã§ã³ã®ååãå€æŽããããšãæ€èšã§ããŸãã äœãã®ãããªãã®ïŒ
c#
public void AddEnumerableHashes<T>(IEnumerable<T> enumerable);
public void AddEnumerableHashes<T>(T[] array);
public void AddEnumerableHashes<T>(T[] array, int index, int length);
IEqualityComparersã«ãããªãŒããŒããŒããå¿
èŠãã©ããçåã«æããŸãã
ææ¡ïŒã³ã¬ã¯ã·ã§ã³åæåæ§æããµããŒãããããã«ããã«ããŒæ§é äœã«IEnumerable
ãå®è£
ãããŸãã
C#
return new HashCode {
SomeField,
OtherField,
{ SomeString, StringComparer.UTF8 },
{ SomeHashSet, HashSet<int>.CreateSetComparer() }
}.GetHashCode()
ããã¯ãæåã§Add()
åŒã³åºããããã¯ããã«æŽç·ŽãããŠããïŒç¹ã«ãäžæå€æ°ã¯å¿
èŠãããŸããïŒãå²ãåœãŠã¯ãããŸããã
@SLaksãããããããè¯ãæ§æãhttps://github.com/dotnet/csharplang/issues/455ãåŸ
ã€å¯èœæ§ãããããïŒææ¡ã«ãµããŒãããããšä»®å®ïŒã HashCode
ã¯åœã®IEnumerable
ãå®è£
ããå¿
èŠããããŸããã
GetHashCodeïŒïŒããªãŒããŒã©ã€ãããŠããã·ã¥ã³ãŒããçæããªãããšã«ããŸãããããã¯ãååä»ããšåäœã®äž¡æ¹ã®èŠ³ç¹ããå¥åŠãªããã§ãïŒGetHashCodeïŒïŒã¯ãèšç®ãããŠãããã®ã§ã¯ãªãããªããžã§ã¯ãã®ããã·ã¥ã³ãŒããè¿ãå¿ èŠããããŸãïŒã
GetHashCode
ãèšç®ãããããã·ã¥ã³ãŒããè¿ããªãã®ã¯å¥åŠã ãšæããŸãã ããã¯éçºè
ãæ··ä¹±ãããã ãããšæããŸãã ããšãã°ã @ SLaksã¯ã ToHashCode
ã䜿çšãã代ããã«ã圌ã®ææ¡ã§ãã§ã«ããã䜿çšããŠããŸãã
@justinvp GetHashCode()
ãèšç®ãããããã·ã¥ã³ãŒããè¿ããªãå Žåã¯ããããã[Obsolete]
ããã³[EditorBrowsable(Never)]
ãšããŒã¯ããå¿
èŠããããŸãã
äžæ¹ã§ãèšç®ãããããã·ã¥ã³ãŒããè¿ãããšã«ãã害ã¯èŠãããŸããã
@terrajobst
GetHashCode()
ããªãŒããŒã©ã€ãããŠããã·ã¥ã³ãŒããçæããªãããšã«ããŸãããããã¯ãååä»ããšåäœã®äž¡æ¹ã®èŠ³ç¹ããå¥åŠãªããã§ãïŒGetHashCode()
ã¯ããªããžã§ã¯ãã®ããã·ã¥ã³ãŒãã§ã¯ãªãããªããžã§ã¯ãã®ããã·ã¥ã³ãŒããè¿ãå¿ èŠããããŸãïŒèšç®äžïŒã
ã¯ãã GetHashCode()
ã¯ãªããžã§ã¯ãã®ããã·ã¥ã³ãŒããè¿ãå¿
èŠããããŸããã2ã€ã®ããã·ã¥ã³ãŒããç°ãªãå¿
èŠãããçç±ã¯ãããŸããïŒ åãå
éšç¶æ
ãæã€HashCode
2ã€ã®ã€ã³ã¹ã¿ã³ã¹ã¯ã GetHashCode()
ããåãå€ãè¿ããããããã§ãæ£ããã§ãã
@terrajobstããªãã®ã³ã¡ã³ããèŠãŸããã è¿ä¿¡ãé ããããšããèš±ããã ãããã©ãã«ãè¡ããªãã£ãã®ã¯äœåºŠãè¡ã£ããæ¥ããããã ãã ãšæã£ãã®ã§ãéç¥ã調ã¹ãã®ãé ãã£ãã§ãã ããã§ãªãããšãèŠãŠããããã§ãïŒ ïŒå€ç°ïŒ
ãããæã«åã£ãŠãã¹ã«ãŒããã/ååžã®æž¬å®ãè¡ãããšãã§ããŠããããã§ãïŒããã¯ãããã®é åã§ã®äœæ¥ã«é¢å¿ãããããšããæå³ã ãšæããŸãïŒã ãã ããããã«ãããã¹ãŠã®ã³ã¡ã³ããèªã¿çµããã®ã«å°ãæéãããããŸãã
@terrajobst
å€æŽã§ããŸãã
public void Add<T>(T[] value);
public void Add<T>(T[] value, int index, int length);
public void Add(byte[] value);
public void Add(byte[] value, int index, int length);
ã«
public void AddRange<T>(T[] values);
public void AddRange<T>(T[] values, int index, int count);
public void AddRange<T>(T[] values, int index, int count, IEqualityComparer<T> comparer);
ïŒ @svickãèšåããåäœãåé¿ããããã«ã Add
-> AddRange
ååãå€æŽããŸããã ãã€ãåºæã®åŠçãå¿
èŠãªå Žåã¯ãã¡ãœããå
ã§typeof(T) == typeof(byte)
ã䜿çšããããšã«ç¹åã§ããããã byte
ãªãŒããŒããŒããåé€ããŸããã ãŸãã value
-> values
ãšlength
-> count
ã æ¯èŒè
ã«éè² è·ããããããšãçã«ããªã£ãŠããŸãã
@terrajobstçç±ãæãåºããŠããã ããŸãã
public void Add(string value);
public void Add(string value, StringComparison comparisonType);
ç§ãã¡ãæã£ãŠãããšãã«å¿ èŠã§ã
public void Add<T>(T value);
public void Add<T>(T value, IEqualityComparer<T> comparer);
ïŒ
@svick
@justinvp GetHashCodeïŒïŒãèšç®ãããããã·ã¥ã³ãŒããè¿ããªãå Žåã¯ããããã[Obsolete]ããã³[EditorBrowsableïŒNeverïŒ]ãšããŒã¯ããå¿ èŠããããŸãã
ïŒ+1ïŒ
@terrajobst ç·šéïŒ HashCode
-> int
ããã®æé»çãªå€æã«æ»ãããšãã§ããã®ã§ã ToHashCode
ã¡ãœããã¯ãããŸãããïŒToHashCode
ã¯åé¡ãããŸããã 以äžã®@CyrusNajmabadiã®å¿çãåç
§ããŠãã ããã
@jamesqo StringComparison
ã¯åæåã§ãã
ãã ãã代ããã«åçã®StringComparer
䜿çšããããšãã§ããŸãã
HashCode-> intããæé»ã®å€æã«æ»ãããšãã§ããã®ã§ãToHashCodeã¡ãœããã¯ãããŸãããïŒ
ç§ãã¡ã¯ããã«ã€ããŠè©±ãåããäŒè°ã§å察ããããšã決å®ããŸããã åé¡ã¯ããŠãŒã¶ãŒãæåŸã®ãintããååŸãããšãäœåãªäœæ¥ãé »ç¹ã«è¡ãããããšã§ãã ã€ãŸããããã·ã¥ã³ãŒãã®å éšã¯å€ãã®å Žåããã¡ã€ãã©ã€ãºã¹ããããå®è¡ããããèªäœãæ°ããç¶æ ã«ãªã»ããããå ŽåããããŸãã æé»ã®å€æã§ãããèµ·ããã®ã¯å¥åŠãªããšã§ãã ãããè¡ã£ãå ŽåïŒ
HashCode hc = ...
int i1 = hc;
int i2 = hc;
ãã®åŸãç°ãªãçµæãåŸãããšãã§ããŸãã
ãã®ãããæ瀺çãªå€æã奜ãã§ã¯ãããŸããïŒäººã ã¯å€æãå éšç¶æ ã®å€æŽãšã¯èããŠããªãããïŒã
ã¡ãœããã䜿çšãããšããããçºçããŠããããšãæ瀺çã«ææžåã§ããŸãã ã§ããã ãå€ãã®ããšãäŒããããã«ãååãä»ããããšãã§ããŸãã ã€ãŸãããToHashCodeAndResetãïŒãã ããããã«å察ããããšã«ããŸããïŒã ããããå°ãªããšãã¡ãœããã«ã¯ããŠãŒã¶ãŒãã€ã³ããªã»ã³ã¹ãªã©ã§èŠãããšãã§ããæ確ãªããã¥ã¡ã³ããå«ããããšãã§ããŸãã ã³ã³ããŒãžã§ã³ã®å Žåã¯ããã§ã¯ãããŸããã
typeofïŒTïŒ== typeofïŒbyteïŒã䜿çšããŠç¹æ®åã§ããããããã€ãã®ãªãŒããŒããŒããåé€ããŸãã
IIRCã¯ãJITã®èŠ³ç¹ãããããããŸããããªãããšã«ã€ããŠããã€ãã®æžå¿µããããŸããã ããããããã¯éå€åã®ãtypeofïŒïŒãã®å Žåã«ã®ã¿åœãŠã¯ãŸãå¯èœæ§ããããŸãã jitãvalue-typetypeofïŒïŒã®å Žåã«å¹æçã«æ£ããããšãè¡ãéããããã¯è¯ãããšã§ãã
@CyrusNajmabadi int
ãžã®å€æã«ç¶æ
ã®å€æŽãå«ãŸããå¯èœæ§ãããããšã«æ°ã¥ããŠããŸããToHashCode
ãã®æã§ãã
æå·ã®èŠ³ç¹ã«ã€ããŠèããŠãã人ã®ããã«-httpïŒ//tuprints.ulb.tu-darmstadt.de/2094/1/thesis.lehmann.pdf
@terrajobst ãç§ã®ã³ã¡ã³ãïŒããããéå§ïŒãèªãã§ã埮調æŽãããAPI圢ç¶ãæ¿èªãããã©ããã決å®ããæéããããŸãããïŒ ãããããªããç§ã¯ãããã°ã©ãã®ããã«api-æ¿èªæžã¿/ã¢ãããšããŒã¯ãããããšãã§ãããšæããŸãããããŠç§ãã¡ã¯ããã·ã¥ã¢ã«ãŽãªãºã ã®æ±ºå®ãå§ããããšãã§ããŸãã
@blowdart ãããªãã匷調ããããã®ç¹å®ã®éšåã¯ãããŸããïŒ
äžèšã§ã¯ããŸãæ確ã§ã¯ãªãã£ããããããŸããããHashDoSã®äŸµå ¥ã«ã€ããŠç§ãç¥ããªãæå·åãããŠããªãããã·ã¥ã¯ãMarvinãšSipHashã ãã§ãã ã€ãŸããã©ã³ãã ãªå€ã§ïŒããšãã°ïŒéé³ãã·ãŒãããããšã§ãããå£ããŠDoSã«äœ¿çšãããå¯èœæ§ããããŸãã
ãªããç§ã¯ãããé¢çœããšæã£ãã ãã§ããã®ããã¥ã¡ã³ãã«ã¯ãæå·åã¢ã«ãŽãªãºã ãä»ããŠçæãããããã·ã¥ã³ãŒãã§ã¯äœ¿çšããªãã§ãã ããããšæžãããŠããã¯ãã ãšæããŸãã
決å®
AddRange
ã¡ãœãããåé€ããå¿
èŠããããŸãã é
åãé »ç¹ã«è¡šç€ºãããå¯èœæ§ã¯ã»ãšãã©ãããŸããã ãããŠããã倧ããªé
åãå«ãŸãããšãåé¡ã¯èšç®ããã£ãã·ã¥ããå¿
èŠããããã©ããã§ãã åŒã³åºãåŽã§forã«ãŒããèŠããšãããã«ã€ããŠèããå¿
èŠãããããšãæããã«ãªããŸããIEnumerable
ãªãŒããŒããŒããAddRange
ã«è¿œå ããããªãã®string
ãšStringComparison
ãå¿
èŠãšããAdd
ãžã®ãªãŒããŒããŒãã¯å¿
èŠãªããšæããŸãã ã¯ãã IEqualityComparer
ãä»ããŠåŒã³åºããããå¹ççã§ããå¯èœæ§ããããŸãããåŸã§ä¿®æ£ã§ããŸããGetHashCode
ããšã©ãŒã§å»æ¢ããããã®ãšããŠããŒã¯ããã®ã¯è¯ãèãã§ãããããã«äžæ©é²ãã§IntelliSenseããé ããŸããããã«ããã次ã®ããšãå¯èœã«ãªããŸãã
`` `CïŒ
//ã³ã¢ã¢ã»ã³ããªã«ååšããŸã
// .NET FrameworkïŒmscorlib
// .NET CoreïŒSystem.Runtime / System.Private.CoreLib
åå空éã·ã¹ãã
{{
public struct HashCode
{{
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public void Add<T>(T value);
public void Add<T>(T value, IEqualityComparer<T> comparer);
[Obsolete("Use ToHashCode to retrieve the computed hash code.", error: true)]
[EditorBrowsable(Never)]
public override int GetHashCode();
public int ToHashCode();
}
}
`` `
次ã®ã¹ãããïŒåé¡ã¯ããã«è§£æ±ºã§ããŸã-å®éšãšããŠhttps://github.com/dotnet/corefx/issues/14354#issuecomment-305028686ãåç §ããŠ
è€éãïŒå€§
誰ãããããæŸãããšã«èå³ããããªããç§ãã¡ã«pingããŠãã ããã äœäººããäžç·ã«äœæ¥ããäœå°ãããããããããŸããã ïŒ @jamesqoã¯ãåé¡ã«æãå€ããæãé·ãæè³ãããããåªå çã«éžæã§ããŸãïŒ
@karelzäžèšã®ã³ã¡ã³ãã«ãããããããç§ã¯æè¯ã®ããã·ã¥ã¢ã«ãŽãªãºã ãéžæããè³æ Œããªããšæãã®ã§ãèããå€ããŸããã @morganbrã«ãªã¹ããããŠããã©ã€ãã©ãªã®ããã€ãã調ã¹ããšãããå®è£ ãéåžžã«è€éã§ããããšãããããŸããããã®ãããèªåã§ãã¹ãããããã«CïŒã«ç°¡åã«å€æããããšã¯ã§ããŸããã ç§ã¯C ++ã®ããã¯ã°ã©ãŠã³ããã»ãšãã©ãªãã®ã§ãã©ã€ãã©ãªãã€ã³ã¹ããŒã«ããŠãã¹ãã¢ããªãäœæããã ãã§ãèŠåŽããŸãã
ããããç§ã¯ãããæ°žé ã«æã«å ¥ããªã¹ãã«æ®ãããšãæãã§ããŸããã ä»æ¥ãã1é±éçµã£ãŠã誰ãåãäžããªãå Žåã¯ãProgrammersSEãŸãã¯Redditã«è³ªåãæçš¿ããããšãæ€èšããŸãã
ç§ã¯ããããã³ãã«å ¥ããŠããŸããïŒãŸãã¯ä»ã®æ¹æ³ã§æé©åããŠããŸããïŒãããããç§ã®å人çãªãããžã§ã¯ãã®ããã€ãã§äœ¿çšããŠããMurmur3ããã·ã¥ã¢ã«ãŽãªãºã ã®åºæ¬çãªå®è£ ã§ãïŒ https ïŒ//gist.github.com/tannergooding/0a12559d1a912068b9aeb4b9586aad7f
ããã§ã®æé©ãªè§£æ±ºçã¯ãå ¥åããŒã¿ã®ãµã€ãºã«åºã¥ããŠããã·ã¥ã¢ã«ãŽãªãºã ãåçã«å€æŽããããšã ãšæããŸãã
äŸïŒMumur3ïŒããã³ãã®ä»ïŒã¯ã倧èŠæš¡ãªããŒã¿ã»ããã«å¯ŸããŠã¯éåžžã«é«éã§ãããåªããåæ£ãæäŸããŸãããå°èŠæš¡ãªããŒã¿ã»ããã«å¯ŸããŠã¯ãããã©ãŒãã³ã¹ãäœäžãïŒåæ£ã§ã¯ãªãé床ïŒã«ãªãå¯èœæ§ããããŸãã
次ã®ãããªããšãè¡ãå¿ èŠããããšæããŸããå šäœã®ãã€ãæ°ãXæªæºã®å Žåã¯ãã¢ã«ãŽãªãºã Aãå®è¡ããŸãã ãã以å€ã®å Žåã¯ãã¢ã«ãŽãªãºã Bãå®è¡ããŸããããã¯ïŒå®è¡ããšã«ïŒæ±ºå®è«çã§ãããå ¥åããŒã¿ã®å®éã®ãµã€ãºã«åºã¥ããŠé床ãšåæ£ãæäŸã§ããŸãã
äžèšã®ã¢ã«ãŽãªãºã ã®ããã€ãã«ã¯SIMDåœä»€çšã«ç¹å¥ã«èšèšãããå®è£
ããããããæãããã©ãŒãã³ã¹ã®é«ããœãªã¥ãŒã·ã§ã³ã«ã¯ãããã¬ãã«ã®FCALLãå«ãŸãããïŒäžéšã®BufferCopyå®è£
ã§è¡ãããããã«ïŒãäŸåé¢ä¿ãååŸããå¿
èŠãããããšã«ã泚æããŠãã ããã System.Numerics.Vector
ã
@jamesqo ãç§ãã¡ã¯éžæã®ãæäŒãããããŠ@tannergoodingãææããŠããããã«ãäžéšã®ã¢ã«ãŽãªãºã ã«ã¯ç¹å¥ãªã³ã³ãã€ã©ãµããŒããå¿ èŠã§ãããçæ³çã«ã¯CïŒã§ãïŒã åè¿°ããããã«ãéžæãããŠããªãåè£ãäœæããå Žåã¯ãåŸã§äœ¿çšããå¯èœæ§ããããŸãã®ã§ãäœæ¥ãç¡é§ã«ãªãå¿é ã¯ãããŸããã
ããŸããŸãªå®è£ ã®ãã³ãããŒã¯ãããããšã¯ç¥ã£ãŠããŸããããã®APIãšå¯èœæ§ã®ããå ¥åç¯å²ïŒ1ã10ãã£ãŒã«ãã®æ§é äœãªã©ïŒã䜿çšããŠæ¯èŒããããšãéèŠã ãšæããŸãã
@tannergooding ããã®çš®ã®é©å¿æ§ãæãããã©ãŒãã³ã¹ãé«ããããããŸããããäœååŒã³åºããããããããªããããAddã¡ãœããã§ã©ã®ããã«æ©èœãããããããŸããã Combineã§ãããè¡ãããšã¯ã§ããŸãããããã¯äžé£ã®AddåŒã³åºãã察å¿ããCombineåŒã³åºããšã¯ç°ãªãçµæãçæããå¯èœæ§ãããããšãæå³ããŸãã
ãŸããå
¥åã®å¯èœæ§ãæãé«ãç¯å²ã4ã32ãã€ãïŒ Combine`1
- Combine`8
ïŒã§ããããšãèãããšããã®ç¯å²ã§ããã©ãŒãã³ã¹ã«å€§ããªå€åããªãããšãé¡ã£ãŠããŸãã
ãã®çš®ã®é©å¿æ§ãæãããã©ãŒãã³ã¹ãé«ããããããŸããããAddã¡ãœãããåŒã³åºãããåæ°ãããããªããããAddã¡ãœããã§ã©ã®ããã«æ©èœãããããããŸããã
ç§ã¯ãAPIã®åœ¢ç¶ãæ±çšããã·ã¥ã«éåžžã«é©ããŠãããšå人çã«ã¯ç¢ºä¿¡ããŠããŸããïŒãã ããè¿ãã§ãïŒ...
çŸåšãéçæ§ç¯çšã®Combine
ã¡ãœãããå
¬éããŠããŸãã ãããããã¹ãŠã®å
¥åãçµã¿åãããŠæçµçãªããã·ã¥ã³ãŒããçæããããšãæå³ããŠããå Žåãååã¯ãpoorãã§ããã Compute
ãããªãã®ãããé©åãããããŸããã
Combine
ã¡ãœãããå
¬éããå Žåã¯ããã¹ãŠã®å
¥åãæ··åããã ãã§ããŠãŒã¶ãŒã¯æåŸã®çµåããã®åºåãšåèšãã€ãæ°ãååŸããFinalize
ã¡ãœãããåŒã³åºãå¿
èŠããããŸããçµã¿åãããŠãæçµçãªããã·ã¥ã³ãŒããçæããŸãïŒããã·ã¥ã³ãŒããæçµåããããšã¯ããããããªã ããåŒãèµ·ããåå ã§ããããéèŠã§ãïŒã
ãã«ããŒãã¿ãŒã³ã§ã¯ã Add
ToHashCode
ã¡ãœãããšAdd
ã¡ãœããããã€ããæ ŒçŽãã ToHashCode
ã®åŒã³åºãã§ã®ã¿çµå/ãã¡ã€ãã©ã€ãºããããšãæå³ããŠãããã©ããïŒãã®å Žåãæ£ããã¢ã«ãŽãªãºã ãåçã«éžæã§ããŸãïŒããŸãã¯ãã®å Žã§çµåããããšãæå³ããŠããã®ã§ããããåœãŠã¯ãŸãããšã¯æããã§ãïŒãããŠãå®è£
ã¯çµåããããã€ãã®åèšãµã€ãºãå
éšçã«è¿œè·¡ããå¿
èŠããããŸãïŒã
ããã»ã©è€éã§ãªãåºçºç¹ãæ¢ããŠãã人ã¯ãxxHash32ãè©ŠããŠãã ããã ããã¯ããªãç°¡åã«CïŒã«å€æãããå¯èœæ§ããããŸãïŒäººã ã¯ãããããŸããïŒã
ãŸã ããŒã«ã«ã§ãã¹ãããŠããŸãããMurmur3ã®CïŒå®è£ ã§æ¬¡ã®ã¹ã«ãŒãããçãèŠãããŸãã
ãããã¯ã1ã8å ¥åã®éçCombineã¡ãœããçšã§ãã
1070.18 mb/s
1511.49 mb/s
1674.89 mb/s
1957.65 mb/s
2083.24 mb/s
2140.94 mb/s
2190.27 mb/s
2245.53 mb/s
ç§ã®å®è£
ã§ã¯ãå
¥åããšã«GetHashCode
ãåŒã³åºãå¿
èŠããããèšç®ãããå€ãè¿ãåã«ç¢ºå®ããå¿
èŠããããšæ³å®ããŠããŸãã
ãã¹ããæãç°¡åãªint
å€ãçµã¿åãããŸããã
ã¹ã«ãŒããããèšç®ããããã«ã10,001åã®å埩ãå®è¡ããæåã®å埩ãããŠã©ãŒã ã¢ãããã®å®è¡ãšããŠç Žæ£ããŸããã
åå埩ã§ã HashCode.Combine
ãåŒã³åºã10,000åã®ãµãå埩ãå®è¡ããåã®ãµãå埩ã®çµæã次ã®å埩ã®æåã®å
¥åå€ãšããŠæž¡ããŸãã
次ã«ããã¹ãŠã®å埩ãå¹³åããŠå¹³åçµéæéãååŸããããã«ãããã«ãŒãããšã«å®è¡ããããµãå埩ã®æ°ã§å²ã£ãŠãåŒã³åºãããšã®å¹³åæéãååŸããŸãã 次ã«ã1ç§ãããã«å®è¡ã§ããåŒã³åºãã®æ°ãèšç®ãããããçµã¿åããããã€ãæ°ã§ä¹ç®ããŠãå®éã®ã¹ã«ãŒããããèšç®ããŸãã
ã³ãŒããã¯ãªãŒã³ã¢ããããŠãå°ãå ±æããŸãã
@tannergooding ãããã¯å€§ããªé²æ©ã®ããã«èãããŸãã æ£ãã枬å®å€ãååŸããŠããããšã確èªããããã«ãAPIã®ç®çã¯ã HashCode.Combine(a, b)
åŒã³åºããåŒã³åºããšåçã§ããããšã§ãã
HashCode hc = new HashCode();
hc.Add(a); // Initializes the hash state, calls a.GetHashCode() and feeds the result into the hash state
hc.Add(b); // Calls b.GetHashCode() and feeds the result into the hash state
return hc.ToHashCode(); // Finalizes the hash state, truncates it to an int, resets the internal state and returns the int
ã©ã¡ãã®å ŽåããããŒã¿ã¯åãå éšããã·ã¥ç¶æ ã«äŸçµŠãããããã·ã¥ã¯æåŸã«1åãã¡ã€ãã©ã€ãºãããå¿ èŠããããŸãã
ð
ããã¯äºå®äžãç§ãæžããã³ãŒããè¡ã£ãŠããããšã§ãã å¯äžã®éãã¯ããã¹ãŠã®ã³ãŒããå¹æçã«ã€ã³ã©ã€ã³åããããšã§ãïŒ new HashCode()
ãå²ãåœãŠãŠãçµåããããã€ãæ°ã远跡ââããå¿
èŠã¯ãããŸãããå®æ°ã§ããããã§ãïŒã
@morganbrã Murmur3ã®å®è£ +ã¹ã«ãŒããããã¹ãïŒ https ïŒ//gist.github.com/tannergooding/89bd72f05ab772bfe5ad3a03d6493650
MurmurHash3ã¯ãããã§èª¬æãããŠããã¢ã«ãŽãªãºã ã«åºã¥ããŠããŸãïŒ https ïŒ ãŸã
xxHash32ïŒBSD-2æ¡é -httpsïŒ//github.com/Cyan4973/xxHash/blob/dev/xxhash.cïŒããã³SpookyHashïŒãããªãã¯ãã¡ã€ã³-httpïŒ//www.burtleburtle.net/bob/hashïŒã§ã®äœæ¥/spooky.htmlïŒããªã¢ã³ã
@tannergoodingç¹°ãè¿ãã«ãªããŸãããããã·ã¥ã®å°é家ã§ã¯ãããŸãããã[èšäºãèªãã§] [1]ãMurmurã¯DoSèæ§ã§ã¯ãªããšèšã£ãŠããã®ã§ããããéžæããåã«ææããã ãã§ãã
@jamesqo ãç§ã¯ééã£ãŠãããããããŸããããè匱æ§ãMurmur3ã§ã¯ãªãMurmur2ã«é©çšãããããšã¯ããªã確信ããŠããŸãã
ãããã®å ŽåããCïŒã®ã¹ã«ãŒãããçµæãååŸã§ããããã«ãããã€ãã®ã¢ã«ãŽãªãºã ãå®è£ ããŠããŸãã ãããã®ã¢ã«ãŽãªãºã ã®ååžããã®ä»ã®ããããã£ã¯ããªãããç¥ãããŠããã®ã§ãåŸã§æé©ãªãã®ãéžæã§ããŸãð
ãã£ãšãèšäºãžã®ãªã³ã¯ãå¿ããŸããïŒ http ïŒ
@tannergoodingOK ã å ¬å¹³ã«èãããŸãïŒ+1ïŒ
@tannergooding ãç§ã¯ããªãã®Murmur3å®è£ ã調ã¹ãŸããããããŠããã¯äžè¬çã«æ£ããèŠããããããããªãããæé©åãããŠããŸãã ç§ãæ£ããç解ããŠããããšã確èªããããã«ãcombinedValueãšMurmurã®å éšç¶æ ãäž¡æ¹ãšã32ãããã§ãããšããäºå®ã䜿çšããŠããŸããïŒ ããã¯ãããããã®å Žåã®ããªãè¯ãæé©åã§ãããç§ã®ä»¥åã®æ··ä¹±ã®ããã€ãã説æããŠããŸãã
ãããæ¡çšããå Žåã¯ãããã€ãã®èª¿æŽãå¿ èŠã«ãªãå¯èœæ§ããããŸãïŒãã ããããã©ãŒãã³ã¹ã®æž¬å®ã«ã¯å€§ããªéãã¯ãããŸããïŒã
ãã®éãç§ã¯ãã®APIãåŸ
ã¡æãã§ããŸããã (field1, field2, field3).GetHashCode()
ä»ããŠGetHashCodeãå®è£
ããããšã¯ã©ãã»ã©æªãããšã§ããïŒ
@ jnm2 ãValueTupleããã·ã¥ã³ãŒãã³ã³ãã€ããŒã¯ãå ¥åãããã·ã¥ã³ãŒãå ã§é çªã«äžŠã¹ãåŸåããããŸãïŒãããŠææ°ã®ãã®ãç Žæ£ããŸãïŒã ããã€ãã®ãã£ãŒã«ããšçŽ æ°ã§å²ãããã·ã¥ããŒãã«ã®å Žåãæ°ä»ããªããããããŸããã å€ãã®ãã£ãŒã«ããŸãã¯2ã®çŽ¯ä¹ã§é€ç®ããããã·ã¥ããŒãã«ã®å ŽåãæåŸã«æ¿å ¥ãããã£ãŒã«ãã®ãšã³ããããŒããè¡çªããããã©ããã«æã圱é¿ããŸãïŒããšãã°ãæåŸã®ãã£ãŒã«ããããŒã«å€ãŸãã¯å°ããæŽæ°ã®å Žåãããããå€ãã®è¡çªãçºçããŸããããããGUIDã®å Žåã¯ãããããçºçããŸããïŒã
ValueTupleã¯ããã¹ãŠ0ã®ãã£ãŒã«ãã§ãããŸãæ©èœããŸããã
ã¡ãªã¿ã«ãç§ã¯ä»ã®å®è£ ã§ã®äœæ¥ããããªããã°ãªããŸããã§ããïŒåªå 床ã®é«ãäœæ¥ããããŸãïŒã ãã€åãæ»ãããšãã§ãããããããŸããã
ã§ã¯ããããæ§é ååã«ã¯ååã§ãªãå Žåããªãã¿ãã«ã«ã¯ååãªã®ã§ããïŒ
@ jnm2 ãããããã®æ©èœãæ§ç¯ãã䟡å€ãããçç±ã®1ã€ã§ãããã¬ãŒã ã¯ãŒã¯å šäœã§æšæºä»¥äžã®ããã·ã¥ã眮ãæããããšãã§ããŸãã
ããã©ãŒãã³ã¹ãšå質ã®ç¹æ§ãåããããã·ã¥é¢æ°ã®å€§ããªããŒãã«ïŒ
https://github.com/leo-yuriev/t1ha
@aresprããŒã ã¯ããã·ã¥é¢æ°ã®CïŒå®è£ ãæ¢ããŠãããšæããŸãã ã§ããå ±æããŠãããŠããããšãã
@tannergoodingãŸã ãã®åé¡ãåãæ»ãããšãã§ããŸãããïŒ ãããããªããç§ãã¡ã¯ããã·ã¥ã®å°é家ãæ¢ããŠããããšãReddit / Twitterã«æçš¿ããŸãã
ç·šéïŒ Redditã«æçš¿ããŸããã https://www.reddit.com/r/csharp/comments/6qsysm/looking_for_hash_expert_to_help_net_core_team/?ref=share&ref_source=link
@jamesqo ãåªå 床ã®é«ããã®ãããã€ãããã3é±é以å ã«ããã«å°éã§ããªããªããŸãã
ãŸããçŸåšã®æž¬å®å€ã¯ãçŸåšCïŒã§ã³ãŒãã£ã³ã°ã§ãããã®ã«ãã£ãŠå¶éãããŸããããããåé¡ã«ãªããšïŒhttps://github.com/dotnet/designs/issues/13ïŒã枬å®å€ãå€å°å€åããå¯èœæ§ããããŸãã ;ïŒ
ãŸããçŸåšã®æž¬å®å€ã¯ãçŸåšCïŒã§ã³ãŒãã£ã³ã°ã§ãããã®ã«ãã£ãŠå¶éãããŸããããããåé¡ã«ãªããšïŒdotnet / designsïŒ13ïŒã枬å®å€ãå€å°å€åããå¯èœæ§ããããŸã;ïŒ
ããã¯åé¡ãããŸãããçµã¿èŸŒã¿é¢æ°ãå©çšå¯èœã«ãªã£ããããã€ã§ãããã·ã¥ã¢ã«ãŽãªãºã ãå€æŽã§ããŸããããã·ã¥ã³ãŒããã«ãã»ã«å/ã©ã³ãã åãããšããããå¯èœã«ãªããŸãã çŸåšã®ç¶æ ã®ã©ã³ã¿ã€ã ã§æé«ã®ããã©ãŒãã³ã¹ãšé ä¿¡ã®ãã¬ãŒããªããæäŸãããã®ãæ¢ããŠããŸãã
@jamesqo ãå©ããŠããã人ãæ¢ããŠãããŠããããšãã ããã·ã¥ã®å°é家ã§ã¯ãªã誰ããããã«åãçµãã§ãããããšãå¬ããæããŸã-ä»ã®èšèªããã¶ã€ã³ããããã€ãã®ã¢ã«ãŽãªãºã ãCïŒã«ç§»æ€ããŠãããã©ãŒãã³ã¹æž¬å®ãè¡ãããšãã§ãã誰ããæ¬åœã«å¿ èŠã§ãã åè£è ãéžæããããå°é家ãå€æŽã«å¯ŸããŠè¡ãããšãè¡ããŸããã³ãŒãã®æ£ç¢ºæ§ãããã©ãŒãã³ã¹ãã»ãã¥ãªãã£ãªã©ã確èªããŸãã
ããïŒ ãã£ã¹ã«ãã·ã§ã³ãèªã¿çµãããšããã§ãããå°ãªããšãç§ã«ã¯ãmurmur3-32PoCãæ¯æããŠã±ãŒã¹ã¯åŒ·åã«ã¯ããŒãºãããŠããããã§ãã ãšããã§ãããã¯ç§ã«ãšã£ãŠéåžžã«è¯ãéžæã®ããã«æããŸãããã以äžäžå¿
èŠãªäœæ¥ãè¡ããªãããšããå§ãããŸãïŒãã ãã .Add()
ã¡ã³ããŒãåé€ããããšãã§ããŸã...ïŒã
ãããã誰ããããå€ãã®ããã©ãŒãã³ã¹äœæ¥ãç¶ããããšãããŸããªã±ãŒã¹ã§ã¯ãxx32ãxx64ãhsip13 / 24ãseahashãmurmur3-x86 / 32ã®ã³ãŒããæäŸã§ããŸãïŒãããŠãäžããmarvin32 implãçµ±åããŸããïŒããããŠïŒãŸã æé©åãããŠããªãïŒsip13 / 24ãspookyv2ã Cityã®äžéšã®ããŒãžã§ã³ã¯ãå¿ èŠã«å¿ããŠç§»æ€ããã®ã«ååç°¡åã«ââèŠããŸãã ãã®ååæŸæ£ããããããžã§ã¯ãã¯ããããã«ç°ãªããŠãŒã¹ã±ãŒã¹ã念é ã«çœ®ããŠãããããææ¡ãããAPIã«ã¯HashCodeã¯ã©ã¹ã¯ãããŸããã ãããããã³ãããŒã¯ã®å Žåãããã¯ããã»ã©éèŠã§ã¯ãããŸããã
ééããªããªãçç£å¯Ÿå¿ïŒã³ãŒããã³ããŒãã¹ã¿ãªã©ã®ãã«ãŒããã©ãŒã¹ãã¢ã°ã¬ãã·ãã€ã³ã©ã€ã³ãšå±éºãªã®çã¹ãããŒã«ã®å¯å€§ãªéãé©çšããŸãã ãšã³ãã£ã¢ã³ã¯ååšãããæŽåãããŠããªãèªã¿åããååšããŸããã ref-impl test-vectorsã«å¯Ÿãããã¹ãã§ãããå©æ²çã«ãäžå®å šããšèšããŸãã
ãããå°ãã§ãå©ãã«ãªãå Žåã¯ã次ã®2é±éã§ãæãã²ã©ãåé¡ãä¿®æ£ããã³ãŒããšããã€ãã®äºåçãªçµæãå©çšã§ããããã«ããã®ã«ååãªæéãèŠã€ããå¿ èŠããããŸãã
@gimpf
ãã£ã¹ã«ãã·ã§ã³ãèªã¿çµãããšããã§ãããå°ãªããšãç§ã«ã¯ãmurmur3-32PoCãæ¯æããŠã±ãŒã¹ã¯åŒ·åã«ã¯ããŒãºãããŠããããã§ãã ã©ã®ãšããã§ç§ã«ã¯éåžžã«è¯ãéžæã®ããã«æããŸãããããŠç§ã¯ãã以äžäžå¿ èŠãªä»äºãè²»ãããªãããšããå§ãããŸã
ãããã人ã ã¯ãŸã Murmur3ãæ¯æããŠããŸããã ããã©ãŒãã³ã¹ãšé ä¿¡ã®ãã©ã³ã¹ã®èŠ³ç¹ããã絶察çã«æè¯ã®ã¢ã«ãŽãªãºã ãéžæããŠããããšã確èªãããã®ã§ãç³ãæŸçœ®ããããšã¯ã§ããŸããã
ãããã誰ããããå€ãã®ããã©ãŒãã³ã¹äœæ¥ãç¶ããããšãããŸããªã±ãŒã¹ã§ã¯ãxx32ãxx64ãhsip13 / 24ãseahashãmurmur3-x86 / 32ã®ã³ãŒããæäŸã§ããŸãïŒãããŠãäžããmarvin32 implãçµ±åããŸããïŒããããŠïŒãŸã æé©åãããŠããªãïŒsip13 / 24ãspookyv2ã Cityã®äžéšã®ããŒãžã§ã³ã¯ãå¿ èŠã«å¿ããŠç§»æ€ããã®ã«ååç°¡åã«ââèŠããŸãã
ã¯ãããé¡ãããŸãïŒ ãã¹ãããããã«ãã§ããã ãå€ãã®ã¢ã«ãŽãªãºã ã®ã³ãŒããåéããããšèããŠããŸãã ããªããè²¢ç®ã§ãããã¹ãŠã®æ°ããã¢ã«ãŽãªãºã ã¯äŸ¡å€ããããŸãã Cityã¢ã«ãŽãªãºã ã移æ€ã§ããã°å¹žãã§ãã
ééããªãæ¬çªç°å¢ã«å¯Ÿå¿ããŠããŸãããã³ãŒãã¯ãã³ããŒãã¹ã¿ãã¢ã°ã¬ãã·ãã€ã³ã©ã€ã³ã®çæ§ã¹ãããŒã«çŸè±¡ãå®å šã§ãªããªã©ã倧éã®ãã«ãŒããã©ãŒã¹ãé©çšããŸãã ãšã³ãã£ã¢ã³ã¯ååšãããæŽåãããŠããªãèªã¿åããååšããŸããã ref-impl test-vectorsã«å¯Ÿãããã¹ãã§ãããå©æ²çã«ãäžå®å šããšèšããŸãã
ããã§å€§äžå€«ã§ãã ã³ãŒããæã¡èŸŒãã ãã§ãå¿ èŠã«å¿ããŠä»ã®èª°ããã³ãŒããèŠã€ããããšãã§ããŸãã
ãããå°ãã§ãå©ãã«ãªãå Žåã¯ã次ã®2é±éã§ãæãã²ã©ãåé¡ãä¿®æ£ããã³ãŒããšããã€ãã®äºåçãªçµæãå©çšã§ããããã«ããã®ã«ååãªæéãèŠã€ããå¿ èŠããããŸãã
ã¯ããããã¯çŽ æŽãããããšã§ãïŒ
@jamesqoããããŸãããäœãèŠãããããšãããã°ãã¡ã¢ã
@gimpfã¯æ¬åœã«çŽ æŽããããšæããŸããé²è¡ç¶æ³ã«ã€ããŠãèãããã ããïŒãã¹ãŠã®ã¢ã«ãŽãªãºã ãå®è¡ã§ããããã«ãªããŸã§åŸ ã€å¿ èŠã¯ãããŸããïŒïŒã ã³ãŒããæ£ããçµæãçæããããã©ãŒãã³ã¹ãæ¬çªç°å¢ã«å¯Ÿå¿ããå®è£ ã§èŠããããã®ãé©åã«è¡šçŸããŠãããšç¢ºä¿¡ããŠããéããæ¬çªç°å¢ã«å¯Ÿå¿ããŠããªããŠãåé¡ãããŸããã åè£è ãéžãã ããé«å質ã®å®è£ ãå®çŸããããã«ããªããšååããããšãã§ããŸãã
seahashã®ãšã³ããããŒãä»ã®ã¢ã«ãŽãªãºã ãšã©ã®ããã«æ¯èŒããããã«ã€ããŠã®åæãèŠãããšããããŸããã ããã«ã€ããŠäœãã¢ããã€ã¹ã¯ãããŸããïŒ èå³æ·±ããµãŠã³ãããã©ãŒãã³ã¹ã®ãã¬ãŒããªãããããŸã...ãã¯ãã«åã¯éãèãããŸãããã¢ãžã¥ã©ãŒæŒç®ã¯é ãèãããŸãã
@morganbrãã£ãŒã¶ãŒã®æºåãã§ããŸããã
SeaHashã«ã€ããŠïŒããããå質ã«ã€ããŠã¯ãŸã ããããŸããã ããã©ãŒãã³ã¹ããããããå Žåã¯ãSMHasherã«è¿œå ããŸãã å°ãªããšãäœè ã¯ãããè¯ããšäž»åŒµãïŒãã¡ã€ã«ã·ã¹ãã ã®ãã§ãã¯ãµã ã«ããã䜿çšããïŒããŸãæ··åäžã«ãšã³ããããŒãæšãŠãããªããšäž»åŒµããŸãã
ããã·ã¥ãšãã³ãããŒã¯ã«ã€ããŠïŒProject Haschisch.Kastriert ãxx32ãxx64ãhsip13ãhsip24ãmarvin32ãseaãmurmur3-32ãæ¯èŒããwikiããŒãžã
ããã€ãã®éèŠãªèŠåïŒ
第äžå°è±¡ïŒ
HashSet<>
ã«ã¢ã¯ã»ã¹ããããã®ããã³ãããŒã¯ãã¯ããã¹ãŠãã»ãŒæž¬å®èª€å·®ã®ç¯å²å
ã«ãããããäœæ¥ãå¿
èŠã§ãïŒå€§ããªéãã¯èŠãŸããããããã§ã話ã䟡å€ã¯ãããŸããïŒç¶æ³ãå°ãæ¹åãããããããäžåºŠãæçŽãå·®ãäžããŸãã
@gimpf ãããã¯çŽ æŽãããã¹ã¿ãŒãã§ãïŒ ã³ãŒããšçµæã確èªããŸããããããã€ã質åããããŸãã
HashSetã®çµæã¯ç¹ã«èå³æ·±ããã®ã§ãã 圌ããæã¡ããããŠããå Žåãããã¯ããéãããã·ã¥æéãããããè¯ããšã³ããããŒã奜ãããã®å¯èœãªã±ãŒã¹ã§ãã
@morganbrä»é±æ«ã¯ãªã³ãšãªããå€ãã£ãã®ã§ãé²æã¯éãããŠããŸãã
ããªãã®è³ªåã«ã€ããŠïŒ
- ããªãã®çµæã¯ãããé ãã®Murmur3aã@tannergoodingããã5åçšåºŠãšããŠSimpleMultiplyAddã瀺ããŸããã ããã¯å¥åŠã«æããŸã...
ç§ã¯èªåèªèº«ãäžæè°ã«æã£ãŠããŸããã ããã¯ã³ããŒ/貌ãä»ããšã©ãŒã§ãããSimpleMultiplyAddã¯åžžã«4ã€ã®å€ãçµåããŠããŸãã...ãŸããäžéšã®ã¹ããŒãã¡ã³ãã䞊ã¹æ¿ããããšã«ãããmultiply-addã³ã³ãã€ããŒããããã«é«éã«ãªããŸããïŒã¹ã«ãŒããããçŽ60ïŒ åäžïŒã
ããªãã®å®è£ ããã®Murmurå®è£ ã«ãªãäžè¬çãªéå¹çæ§ãæã£ãŠããå¯èœæ§ã¯ãããŸããããããšããããæ±çšå®è£ ããã倧ããªå©ç¹ãããã«ã¹ã¿ã å®è£ ãšããŠèªãå¿ èŠããããŸããïŒ
ç§ã¯ããã€ãã®ããšãèŠéããŠããå¯èœæ§ããããŸããã.NETã®å Žåãæ±çšå®è£ ã¯ãã®ãŠãŒã¹ã±ãŒã¹ã§ã¯äœ¿çšã§ããªãããã§ãã ç§ã¯ãã¹ãŠã®ã¢ã«ãŽãªãºã ã«å¯ŸããŠCombineã¹ã¿ã€ã«ã®ã¡ãœãããäœæããŸããããwrtããã·ã¥ã³ãŒããçµã¿åããããšãæ±çšã¡ãœãããããã¯ããã«åªããããã©ãŒãã³ã¹ãçºæ®ããŸãã
ãã ãããããã®å®è£ ã§ããé ãããŸãã ãããªãäœæ¥ãå¿ èŠã§ãã ãã®é åã§ã®.NETã®ããã©ãŒãã³ã¹ã¯ãç§ã«ã¯ãŸã£ããäžéæã§ãã ããŒã«ã«å€æ°ã®ã³ããŒãè¿œå ãŸãã¯åé€ãããšãããã©ãŒãã³ã¹ã2åç°¡åã«å€ããå¯èœæ§ããããŸãã æé©ãªãªãã·ã§ã³ãéžæããããã«ååã«æé©åãããå®è£ ãæäŸã§ããªãå¯èœæ§ããããŸãã
- 1ã2ãããã³4ã®çµã¿åããã§çµæãåŸãããã®ã¯è¯ãããšã§ããããã®APIã¯æ倧8ã€ã«ãªããŸãã
çµåãã³ãããŒã¯ãæ¡åŒµããŸããã ãã®é¢ã§é©ãã¯ãããŸããã
- X64ã§å®è¡ããŠããã®ãèŠãŸããïŒ...ïŒãX86ã®çµæãç°¡åã«ååŸã§ããŸããïŒ
ãã€ãŠã¯ããã§ãããããã®åŸ.NETStandardã«ç§»æ€ããŸããã ä»ãç§ã¯äŸåé¢ä¿å°çã«ããŸãããããŠ.NET Core2ãšCLR64ããããã³ãããŒã¯ã ããæ©èœããŸãã çŸåšã®åé¡ã解決ããã°ãããã¯ç°¡åã«è§£æ±ºã§ããŸãã
ããã§v2.1ãªãªãŒã¹ã«ãªããšæããŸããïŒ
@gimpfãã°ããæçš¿ããŠããŸããããå®è£ ã®é²æç¶æ³ãæŽæ°ããŠããŸããïŒ ïŒã¹ãã€ãªãŒïŒ
@jamesqoå¥åŠãªçµæãåŒãèµ·ããããã€ãã®ãã³ãããŒã¯ãä¿®æ£ããCity32ãSpookyV2ãSip13ãããã³Sip24ã䜿çšå¯èœãªã¢ã«ãŽãªãºã ã®ãªã¹ãã«è¿œå ããŸããã Sipsã¯ïŒxx64ã®ã¹ã«ãŒããããšæ¯èŒããŠïŒæåŸ ã©ããã«é«éã§ãããCityãšSpookyã¯ããã§ã¯ãããŸããïŒSeaHashã«ã€ããŠãåãããšãèšããŸãïŒã
ããã·ã¥ã³ãŒããçµã¿åãããå ŽåãMurmur3-32ã¯ãŸã è¯ãè³ãã®ããã«èŠããŸãããç§ã¯ãŸã ãã培åºçãªæ¯èŒãå®è¡ããŠããŸããã
å¥ã®æ³šæç¹ãšããŠãã¹ããªãŒãã³ã°APIïŒ.AddïŒïŒïŒã«ã¯ãåè£ã®ãªã¹ãããããã€ãã®ããã·ã¥ã¢ã«ãŽãªãºã ãåé€ãããšããäžå¹žãªå¯äœçšããããŸãã ãã®ãããªAPIã®ããã©ãŒãã³ã¹ã«ãçåãããããšãèãããšãæåããæäŸãããã©ãããåèããããšããå§ãããŸãã
.Add()
éšåãåé¿ãããããã·ã¥ã³ã³ãã€ããŒãã·ãŒãã䜿çšããŠããããšãèãããšãtgã®ã³ã³ãã€ããŒã®ã¯ãªãŒã³ã¢ãããå°ããªãã¹ãã¹ã€ãŒãã®äœæãããã³ããã1æ¥ãšåŒã³ãŸãã é±æ«ã¯æ°æéãããªããããã©ãŒãã³ã¹ã®æé©åã¯ããé¢åãªã®ã§ãéã¡ããããŒãžã§ã³ãäœæãããšå°ãæéããããå¯èœæ§ããããŸã...
@gimpf ãããã¯å€§ããªé²æ©ã®ããã«èãããŸãã 決å®ãäžããŠåé²ããã®ã«ååãã©ããã確èªã§ããããã«ãçµæããŒãã«ãæå ã«ãããŸããïŒ
@morganbrãã³ãããŒã¯çµæãæŽæ°ããŸããã
ä»ã®ãšããã.NET Core 2ã§ã®çµæã¯64ãããã®ã¿ã§ãããã®ãã©ãããã©ãŒã ã§ã¯ãã·ãŒããªãã®City64ããã¹ãŠã®ãµã€ãºã§æéã§ãã ã·ãŒããçµã¿èŸŒãã XX-32ã¯Murmur-3-32ãšçµã³ã€ããŠããŸãã 幞ããªããšã«ããããã¯32ããããã©ãããã©ãŒã ã§é«éã§ãããšããè©å€ã®ããåãã¢ã«ãŽãªãºã ã§ãããæããã«ããããç§ã®å®è£ ã«ãåœãŠã¯ãŸãããšã確èªããå¿ èŠããããŸãã SeaãšSpookyV2ãç°åžžã«é ãããã«èŠããããšãé€ããŠãçµæã¯å®éã®ããã©ãŒãã³ã¹ã代衚ããŠããããã§ãã
hash-code-combinersã®hash-dosä¿è·ãå®éã«ã©ãã ãå¿ èŠããèæ ®ããå¿ èŠããããŸãã ããã·ã¥ãæ°žç¶æ§ã«æããã«äœ¿çšã§ããªãããã«ããããã ãã«ã·ãŒããå¿ èŠãªå Žåã¯ã32ãããã·ãŒããšXORãå®è¡ãããšcity64ãæ¹åãããŸãã ãã®ãŠãŒãã£ãªãã£ã¯ããã·ã¥ãçµã¿åãããããã ãã«ãããŸãïŒããšãã°ãæååã®ããã·ã¥ã³ãŒãã眮ãæããããæŽæ°é åã®ããããã€ã³ããã·ã¥ã«ããããšã¯ã§ããŸããïŒã®ã§ãããã§ååãããããŸããã
OTOHãå¿ èŠã ãšæãå ŽåãSip13ã¯éåžžXX-32ïŒ64ããããã©ãããã©ãŒã ïŒããã50ïŒ æªæºé ãããšãããããŸããããã®çµæã¯32ãããã¢ããªã§ã¯å€§å¹ ã«ç°ãªãå¯èœæ§ããããŸãã
ãããcorefxã«ã©ãã ãé¢é£ããŠãããã¯ããããŸããããLegacyJit 32ãããïŒFW 4.7ä»ãïŒã®çµæãè¿œå ããŸããã
çµæã¯ã°ãããŠé ããšèšãããã§ãã ãã ããäŸãšããŠã56 MiB / s察319MiB / sã§ã¯ç¬ã£ãŠããŸããïŒããã¯Sipã§ãããå·Šå転ã®æé©åãæãäžè¶³ããŠããŸãïŒã 1æã«.NETããã·ã¥ã¢ã«ãŽãªãºã ãããžã§ã¯ãããã£ã³ã»ã«ããçç±ãèŠããŠãããšæããŸã...
ãããã£ãŠãRyuJit-32ãããã¯ãŸã æ¬ èœããŠãããïŒããŸãããã°ïŒéåžžã«ç°ãªãçµæãåŸãããŸãããLegacyJit-x86ã®å ŽåãMurmur-3-32ãæ軜ã«åã¡ãCity-32ãšxx-32ã®ã¿ãè¿ã¥ãããšãã§ããŸãã éé³ã¯ãïŒåããã·ã³äžã§ïŒ0.6ã2 GB / sã§ã¯ãªã0.4ã1.1 GB / sçšåºŠã§ããã©ãŒãã³ã¹ãäœäžããŸãããå°ãªããšãé©åãªçå Žã«ãããŸãã
ä»å€ãããã€ãã®ããã¯ã¹ã§ãã³ãããŒã¯ãå®è¡ããçµæãæçš¿ããŸãïŒRyzenãi7ãXeonãA10ãi7 Mobileãããã³ä»ã®ããã€ãã®ããã¯ã¹ã ãšæããŸãïŒã
@ tannergooding @ morganbrããã€ãã®çŽ æŽãããã¢ããããŒããšããã€ãã®éèŠãªã¢ããããŒãã
æåã«éèŠïŒ
ããããšïŒ
ãEmptyãïŒçŽç²ãªãªãŒããŒãããïŒããmultiply-addãïŒæåãªSOåçã®é床æé©åããŒãžã§ã³ïŒãªã©ãããã·ã¥ã³ãŒããçµã¿åãããããã®ãã¹ãŠã®äž»èŠãªå®è£ ã§ã¹ã€ãŒããå®è¡ããã«ã¯ïŒ
bin\Release\net47\Haschisch.Benchmarks.Net47.exe -j:clr_x86 -j:clr_x64_legacy -j:clr_x64 -j:core_x64 -- CombineHashCode --allcategories=prime
ïŒ_32ãããã³ã¢ãã³ãããŒã¯ãå®è¡ããã«ã¯ããã¬ãªãªãŒã¹ã®BenchmarkDotNetãå¿ èŠãªããã§ãïŒãŸãã¯ã32ãããã®ã¿ã®ã»ããã¢ãããšã³ã¢ããŒã¹ã®ãã³ãã©ã³ããŒã䜿çšããå¿ èŠããããŸãïŒããã®åŸã-jïŒcore_x86ã䜿çšããŠåäœããã¯ãã§ãïŒ_
çµæïŒãã¹ãŠã®ãã°ä¿®æ£ã®åŸãxx32ã¯ãã¢ãã€ã«Haswelli7äžã®Windows10ã§ããã¯ã€ãã¯ãå®è¡ã§64ãããRyuJITã䜿çšãããã¹ãŠã®ãªãŒããŒããŒãã«åã€ããã§ãã Sipsãšmarvin32ã®éã§ã¯ãSip-1-3ãåžžã«åã¡ãŸãã Sip-1-3ã¯xx32ãããçŽ4åé ãããããããªããã£ããªä¹ç®å ç®ã³ã³ãã€ããŒãããçŽ2åé ããªããŸãã 32ãããã³ã¢ã®çµæã¯ãŸã æ¬ èœããŠããŸãããç§ã¯å€ããå°ãªããããã®åé¡ã解決ããå®å®ããBenchmarkDotNetãªãªãŒã¹ãåŸ ã£ãŠããŸãã
ïŒç·šéïŒããã·ã¥ã»ããã«ã¢ã¯ã»ã¹ããããã®ãã³ãããŒã¯ã®ã¯ã€ãã¯ã©ã³ãè¿œå ããŸããã ããã¯æããã«ãäžèšã®Âµãã³ãããŒã¯ããã詳现ã«å€§ããäŸåããŠããŸãããå€èŠ³ã確èªããããšããå§ãããŸãã
çŽ æŽãããããŒã¿ãããããšã@gimpf ïŒ ããã決æã«å€ããããšãã§ãããã©ããèŠãŠã¿ãŸãããã
ãŸããã¢ã«ãŽãªãºã ã次ã®ããã«åå²ããŸãã
Fast + Goodãšã³ããããŒïŒé床é ïŒïŒ
HashDoSèæ§ïŒ
競åããïŒé ãïŒïŒ
競åããïŒæªããšã³ããããŒïŒïŒ
åè ãéžã¶åã«ãä»ã®äººãäžèšã®ç§ã®ãã±ãã«åæããããšã確èªããããšæããŸãã ãããæãç«ã€å Žåã¯ãHashDoSã®æµæã«2åãæ¯æããã©ãããéžæããŠãããé床ã§é²ãå¿ èŠããããšæããŸãã
@morganbrããªãã®ã°ã«ãŒãåã¯åé¡ãªãããã§ãã SipHashã©ãŠã³ãã®ããŒã¿ãã€ã³ããšããŠãRustãããžã§ã¯ãã¯ãDJBä»ãã®sip-hashãäœæããJean-PhilippeAumassonã«è³ªåããŸããã ãã®è°è«ã®åŸã圌ãã¯ããã·ã¥ããŒãã«ã®ããã«sip-1-3ã«è¡ãããšã«æ±ºããŸããã
ïŒ PR rustïŒïŒ33940ããã³ä»éããåé¡rustïŒïŒ29754ãåç §ããŠãã ããïŒã
ããŒã¿ãšã³ã¡ã³ãã«åºã¥ããŠããã¹ãŠã®ã¢ãŒããã¯ãã£ã§xxHash32ã䜿çšããããšãææ¡ããããšæããŸãã 次ã®ã¹ãããã¯ãããå®è£ ããããšã§ãã @gimpf ããã®ããã®PRããŸãšããããšã«èå³ããããŸããïŒ
HashDoSãå¿é ãªæ¹ã®ããã«ãMarvin32ãå«ã¿ãSipHashãå«ãå¯èœæ§ã®ããæ±çšããã·ã¥APIã®ææ¡ãããã«ãã©ããŒã¢ããããŸãã ããã¯ã @ gimpfãš@tannergoodingãåãçµãã§ããä»ã®å®è£ ã«ãé©ããå Žæã«ãªããŸãã
@morganbræéã®èš±ãéãPRããŸãšããããšãã§ããŸãã ãŸããåãå ¥ããæžãããªãéããç§ãå人çã«xx32ã奜ã¿ãŸãã
@gimpf ãããªãã®æéã¯ã©ãã§ããïŒ æéããªãå Žåã¯ãä»ã®èª°ããè©ŠããŠã¿ãããã©ããã確èªã§ããŸãã
@morganbr 11æ5æ¥ãŸã§ããããšæã£ãŠããã®ã§ããã2é±é以å ã«æéãèŠã€ããããã®ã¯è¯ãããã§ãã
@gimpf ãããã§ããã æŽæ°ããŠããã ãããããšãããããŸãïŒ
@ terrajobst-ããŒãã£ãŒã«å°ãé ããŠããŸãïŒç³ãèš³ãããŸããïŒããAddã¡ãœããã®æ»ãå€ã®ã¿ã€ããå€æŽããããšã¯ã§ããŸãããïŒ
`` `cïŒ
public HashCode Add
public HashCode Add
The params code is clearly there for scenarios where you have multiple fields, e.g.
```c#
public override int GetHashCode() => new HashCode().Add(Name, Surname).ToHashCode();
ãã ããç¡é§ã®å°ãªãé åå²ãåœãŠã1ã€äœ¿çšããŠãããŸã£ããåãããšããã®ããã«å®çŸã§ããŸãã
c#
public override int GetHashCode() => new HashCode().Add(Name).Add(Surname).Add(Age).ToHashCode();
ã¿ã€ããæ··åšãããããšãã§ããããšã«æ³šæããŠãã ããã ããã¯æããã«ãéåžžã®ã¡ãœããå
ã§æµæ¢ã«åŒã³åºããªãããšã§å®è¡ã§ããŸãã æµæ¢ãªã€ã³ã¿ãŒãã§ãŒã¹ã絶察ã«å¿
èŠãšããããã§ã¯ãªããšãããã®è°è«ãèãããšããªãç¡é§ãªparams
ãªãŒããŒããŒããããããååšããã®ã§ããããã ãã®ææ¡ãæªãææ¡ã§ããå Žåã params
éè² è·ã¯ãŸã£ããåã軞ã«åé¡ãããŸãã ãããšãäºçŽ°ã§ãããªããæé©ãªããã·ã¥ã³ãŒãã®éåžžã®ã¡ãœããã匷å¶ããããšã¯ãå€ãã®ååŒã®ããã«æããŸãã
ç·šéïŒ implicit operator int
ã¯DRYã«ãé©ããŠããŸãããå³å¯ã«ã¯éèŠã§ã¯ãããŸããã
@jcdickinson
Addã¡ãœããã®æ»ãå€ã®ã¿ã€ããå€æŽã§ããŸãããïŒ
ããã«ã€ããŠã¯å€ãææ¡ã§ãã§ã«è°è«ããŸããããåŽäžãããŸããã
ããããç¡é§ãªparamsãªãŒããŒããŒããååšããã®ã¯ãªãã§ããïŒ
paramsãªãŒããŒããŒããè¿œå ããŠããŸãããïŒ ãã®WebããŒãžã®ãparamsãã«å¯ŸããŠCtrl + Fãå®è¡ãããšãã³ã¡ã³ãããã®åèªããããã¢ããããå¯äžã®å Žæã§ããããšãããããŸãã
æé»ã®æŒç®åintãDRYã«é©ããŠããŸãããå³å¯ã«ã¯éèŠã§ã¯ãããŸããã
ãããäžèšã®ã©ããã§è°è«ããããšæããŸã...
@jamesqo説æããããšã
paramsãªãŒããŒããŒã
ç§ã¯AddRange
ãæå³ããŸããããããã«ã¯äœã®çœåŒåããªããšæããŸãã
@jcdickinson AddRange
ã¯å
ã®ææ¡ã«å«ãŸããŠããŸããããçŸåšã®ããŒãžã§ã³ã«ã¯å«ãŸããŠããŸããã APIã¬ãã¥ãŒã«ãã£ãŠæåŠãããŸããïŒ@terrajobstã«ããhttps://github.com/dotnet/corefx/issues/14354#issuecomment-308190321ãåç
§ïŒïŒ
ã·ããªãªãäžæ確ãªããããã¹ãŠã®
AddRange
ã¡ãœãããåé€ããå¿ èŠããããŸãã é åãé »ç¹ã«è¡šç€ºãããå¯èœæ§ã¯ã»ãšãã©ãããŸããã ãããŠããã倧ããªé åãå«ãŸãããšãåé¡ã¯èšç®ããã£ãã·ã¥ããå¿ èŠããããã©ããã§ãã åŒã³åºãåŽã§forã«ãŒããèŠããšãããã«ã€ããŠèããå¿ èŠãããããšãæããã«ãªããŸãã
@gimpfç§ã¯xxHash32ã§ææ¡ãããªãã£ã«ããŸããã ãã®å®è£ ãèªç±ã«å ¥æããŠãã ããã å®éã®xxHash32ãã¯ãã«ã«å¯Ÿãããã¹ãããããŸãã
ã€ã³ã¿ãŒãã§ãŒã¹ã«ã€ããŠã ç§ã¯ã¢ã°ã©ãã«ããå±±ãäœã£ãŠããããšãååã«æ¿ç¥ããŠããŸã-ç¡èŠããŠããŸããŸããã ç§ã¯æ¬ç©ã«å¯ŸããŠçŸåšã®ææ¡ã䜿çšããŠããŸãããããŠããã¯å€ãã®è¿·æãªç¹°ãè¿ãã§ãã
ç§ã¯ã€ã³ã¿ãŒãã§ãŒã¹ãããã£ãŠã¿ãŸããããæµæ¢ãªã€ã³ã¿ãŒãã§ãŒã¹ãæåŠãããçç±ãç解ããŸããã ããªãé ãã§ãã
BenchmarkDotNet=v0.10.9, OS=Windows 10 Redstone 2 (10.0.15063)
Processor=Intel Core i7-4800MQ CPU 2.70GHz (Haswell), ProcessorCount=8
Frequency=2630626 Hz, Resolution=380.1377 ns, Timer=TSC
.NET Core SDK=2.0.2
[Host] : .NET Core 2.0.0 (Framework 4.6.00001.0), 64bit RyuJIT
DefaultJob : .NET Core 2.0.0 (Framework 4.6.00001.0), 64bit RyuJIT
ã€ã³ã©ã€ã³åãããŠããªãã¡ãœãããããã·ã¥ã³ãŒããœãŒã¹ãšããŠäœ¿çšããã Addãšæµæ¢ãªæ¡åŒµã¡ãœããã®50åã®åŒã³åºãïŒ
| æ¹æ³| å¹³å| ãšã©ãŒ| StdDev | ã¹ã±ãŒãªã³ã°|
| ------- | ---------ïŒ| ---------ïŒ| ---------ïŒ| -------ïŒ |
| è¿œå | 401.6 ns | 1.262 ns | 1.180 ns | 1.00 |
| ã¿ãªãŒ| 747.8 ns | 2.329 ns | 2.178 ns | 1.86 |
ãã ãã次ã®ãã¿ãŒã³ã¯æ©èœããŸãã
`` `cïŒ
public struct HashCodeïŒSystem.Collections.IEnumerable
{{
[EditorBrowsableïŒEditorBrowsableState.NeverïŒ]
[å»æ¢ïŒ "ãã®ã¡ãœããã¯ã³ã¬ã¯ã·ã§ã³åæåæ§æçšã«æäŸãããŠããŸãã"ããšã©ãŒïŒtrueïŒ]
public IEnumerator GetEnumeratorïŒïŒ=>æ°ããNotImplementedExceptionïŒïŒ;ãã¹ããŒããŸãã
}
public override int GetHashCode() => new HashCode()
{
Age, // int
{ Name, StringComparer.Ordinal }, // use Comparer
Hat // some arbitrary object
}.ToHashCode();
`` `
ãŸããçŸåšã®ææ¡ãšåãããã©ãŒãã³ã¹ç¹æ§ãåããŠããŸãã
| æ¹æ³| å¹³å| ãšã©ãŒ| StdDev | ã¹ã±ãŒãªã³ã°|
| ------------ | ---------ïŒ| ---------ïŒ| ---------ïŒ| --- ----ïŒ|
| è¿œå | 405.0 ns | 2.130 ns | 1.889 ns | 1.00 |
| ã€ãã·ã£ã©ã€ã¶ãŒ| 400.8 ns | 4.821 ns | 4.274 ns | 0.99 |
æ®å¿µãªãããã³ã³ãã€ã©ãæºè¶³ãããããã«IEnumerable
ãå®è£
ããå¿
èŠããããããããã¯ããããã¯ã§ãã ããã¯èšã£ãŠãã Obsolete
ã¯foreach
ã§ããšã©ãŒã«ãªããŸããäŸå€ã«ééããããã«ã¯ãæ¬åœã«ç©äºãå£ããããšæãå¿
èŠããããŸãã 2ã€ã®MSILã¯åºæ¬çã«åãã§ãã
@jcdickinsonåé¡ãã€ããã§ãããŠããããšãã ã³ã©ãã¬ãŒã¿ãŒã®æåŸ ç¶ããéãããŸãããæ¿è«Ÿããããç¥ãããã ããããã®åé¡ãããªãã«å²ãåœãŠãããšãã§ããŸãïŒåœé¢ã¯èªåã«å²ãåœãŠãŸãïŒã
ãã³ãïŒåæãããšãGitHubã¯ãªããžããªããã®ãã¹ãŠã®éç¥ïŒ1æ¥ããã500以äžïŒã«èªåçã«ãµã€ã³ã¢ããããŸããããããç£èŠãªããã«å€æŽãããšããã¹ãŠã®ã¡ã³ã·ã§ã³ãšåé¡ã®éç¥ãéä¿¡ãããŸãã賌èªããŸããã
@jcdickinson ãç§ã¯è¿·æãªç¹°ãè¿ããé¿ããæ¹æ³ã«ééããªãèå³ããããŸãïŒãã ããåæåæ§æã«ã€ããŠäººã ãã©ã®ããã«æãããã¯ããããŸããïŒã æµæ¢ãã«ã¯2ã€ã®åé¡ããã£ãããšãæãåºããŠããããã§ãã
var hc = new HashCode();
var newHc = hc.Add(foo);
hc.Add(bar);
return newHc.ToHashCode();
ãã®ã¹ã¬ããã®ææ¡ã¯ãã§ã«æ¿èªãããŠããã®ã§ïŒãããŠããããããŒãžããæºåãæŽã£ãŠããã®ã§ïŒãå€æŽãããå Žåã¯æ°ããAPIææ¡ãéå§ããããšããå§ãããŸãã
@ karelz @ gimpfã¯ãã§ã«ãã®åé¡ãäºåã«æããŸãã 圌ã¯å®è£ ã«ç²ŸéããŠããã®ã§ã代ããã«ãã®åé¡ã@gimpfã«å²ãåœãŠãŠãã ããã ïŒç·šéïŒ nvmïŒ
@terrajobstããã«å¯Ÿããåå£å Žã®APIãªã¯ãšã¹ãã®äžçš®ã GetHashCode
å»æ¢ãšããŒã¯ããã®ã§ã HashCode
ã¯ãéåžžã¯äžå€/æ¯èŒå¯èœãªæ§é äœã§ããã«ãããããããæ¯èŒããããšãæå³ããå€ã§ã¯ãªãããšããŠãŒã¶ãŒã«æé»çã«äŒããŠããŸãã ãã®å Žåã Equals
å»æ¢ãšããŒã¯ããå¿
èŠããããŸããïŒ
[Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes.", error: true)]
[EditorBrowsable(Never)]
// If this is too harsh, base.Equals() is fine as long as the [Obsolete] stays
public override bool Equals(object obj) => throw new NotSupportedException("HashCode is a mutable struct and should not be compared with other HashCodes.");
Span
åæ§ã®ããšãè¡ããããšæããŸãã
ãããåãå ¥ããããã°ãç§ã¯æã...
cannot
代ããã«should not
ãŸãã¯may not
ã䜿çšããããšãæ€èšããŸãã@ Joe4evrå
æ°ã§ãã ã³ã¡ã³ããæŽæ°ããŸããã åãã¡ãã»ãŒãžãGetHashCode
äŸå€ã«å«ããããšãæçãªå ŽåããããŸãã
public override int GetHashCode() => throw new NotSupportedException("HashCode is a mutable struct and should not be compared with other HashCodes.");
@morganbrãªããããåéããã®ã§ããïŒ
CoreFXã§å ¬éããããã®PRã¯ãŸã å®äºããŠããŸããã
@gimpfãã³ãããŒã¯ããã³ãŒããå©çšã§ããŸãããããã³/ãŸãã¯SpookilySharpnugetããã±ãŒãžãã©ã®ããã«å ¬æ£ã§ãããããã°ãã確èªã§ããŸããã ç§ã¯2ã3幎ã®åæ»ã®åŸã«ãã®ãããžã§ã¯ããã»ããã§æãããšãæ¢ããŠããŸãããããŠç§ã¯ãããã©ã®ããã«ç«ã¡äžããããèŠãããšæã£ãŠããŸãã
@JonHanna圌ã¯ããã«æçš¿ããŸããïŒ https ïŒ
@JonHanna ãæ±çšã®éæå·åããã·ã¥APIã§äœã圹ç«ã€ããèãå§ããããšãã§ããããã«ããã¹ããã©ã®ããã«è¡ãããããèããããšæããŸãã
@morganbrãã®ãããªAPIã«ã€ããŠè°è«ããããã®é©åãªãã©ãŒã©ã ã¯ã©ãã«ãããŸããïŒ ãã®ãããªAPIã¯ãæå°å ¬åæ¯ã ãã§ãªããåªããAPIã§ãããã倧ããªæ§é äœã®åŠçãæ¹åããå¿ èŠããããšæããŸãã å¥ã®åé¡ã§ããããè¡ããããããããªããã¹ãŠãè°è«ãã...
@gimpfããªãã®ããã«1ã€
@ morganbr-ãã®ã³ããããå«ãããã±ãŒãžåãšããŒãžã§ã³çªå·ãååŸã§ããŸããïŒ
@karelz ãããã±ãŒãž/ããŒãžã§ã³æ å ±ã§@smitpatelãå©ããããšãã§ããã§ããããïŒ
.NETCoreã®ãã€ãªãŒãã«ããè©ŠããŠã¿ãŸãã-ææ¥ãŸã§åŸ
ã¡ãŸãã
åçŽã«äŸåã§ããããã±ãŒãžã¯ãªããšæããŸãã
åå è ãžã®è³ªåã¯ãã¡ãã Roslyn IDEã䜿çšãããšããŠãŒã¶ãŒã¯ã¯ã©ã¹/æ§é äœã®äžé£ã®ãã£ãŒã«ã/ããããã£ã«åºã¥ããŠGetHashCodeimplãçæã§ããŸãã çæ³çã«ã¯ã httpsïŒ //github.com/dotnet/corefx/pull/25013ã§è¿œå ãããæ°ããHashCode.Combineã䜿çšã§ã
æè¿ãç§ãã¡ãçæãããã©ãŒã ã«åé¡ãããããšãããããŸããã ã€ãŸããVBã¯ããã©ã«ãã§ãªãŒããŒãããŒãã§ãã¯ããªã³ã«ããŠã³ã³ãã€ã«ãããããimplã«ãã£ãŠãªãŒããŒãããŒãçºçããŸãã ãŸããVBã«ã¯ãã³ãŒãé åã®ãªãŒããŒãããŒãã§ãã¯ãç¡å¹ã«ããæ¹æ³ããããŸããã ã¢ã»ã³ããªå šäœã§å®å šã«ãªã³ãŸãã¯ãªãã«ãªããŸãã
ãã®ãããç§ãã¡ãæäŸããimplãããããã®åé¡ã«æ©ãŸãããªããã©ãŒã ã«çœ®ãæããããšãã§ããããã«ããããšæããŸãã çæ³çã«ã¯ãçæããããã©ãŒã ã¯æ¬¡ã®ããããã£ãæã¡ãŸãã
a + b + c + d
ãŸãã¯a ^ b ^ c ^ d
çºçããåé¡ããªãããšããã§ã«ç²Ÿæ»ãããŠãããã®ã§ããããšãã°ãVBã®1ã€ã®ãªãã·ã§ã³ã¯ã次ã®ãããªãã®ãçæããããšã§ãã
return (a, b, c, d).GetHashCode()
ãã ããããã¯System.ValueTupleãžã®åç §ããããã©ããã«äŸåããŸãã çæ³çã«ã¯ãããããªããŠãæ©èœããimplãäœæã§ããŸãã
ãããã®å¶çŽãåŠçã§ããé©åãªããã·ã¥ã¢ã«ãŽãªãºã ã«ã€ããŠç¥ã£ãŠãã人ã¯ããŸããïŒ ããããšãïŒ
-
泚ïŒæ¢åã®åºåã³ãŒãã¯æ¬¡ã®ãšããã§ãã
Dim hashCode = -252780983
hashCode = hashCode * -1521134295 + i.GetHashCode()
hashCode = hashCode * -1521134295 + j.GetHashCode()
Return hashCode
ããã¯æããã«ãªãŒããŒãããŒããå¯èœæ§ããããŸãã
ãã®ã³ãŒãã®åšãã«unchecked { }
è¿œå ããã ããªã®ã§ããããCïŒã®åé¡ã§ã¯ãããŸããã ãã®ãã现ããå¶åŸ¡ã¯VBã§ã¯äžå¯èœã§ãã
ãããã®å¶çŽãåŠçã§ããé©åãªããã·ã¥ã¢ã«ãŽãªãºã ã«ã€ããŠç¥ã£ãŠãã人ã¯ããŸããïŒ ããããšãïŒ
ãããšãããªãã¯Tuple.Create(...).GetHashCode()
ããããšãã§ããŸãã æããã«ãããã«ã¯å²ãåœãŠãçºçããŸãããäŸå€ãã¹ããŒããããã¯ãŸãã ãšæãããŸãã
System.ValueTuple
ãã€ã³ã¹ããŒã«ããããã«ãŠãŒã¶ãŒã«æ瀺ã§ããªãçç±ã¯ãããŸããïŒ ããã¯çµã¿èŸŒã¿ã®èšèªæ©èœãªã®ã§ãSystem.ValueTupleããã±ãŒãžã¯åºæ¬çã«ãã¹ãŠã®ãã©ãããã©ãŒã ãšéåžžã«äºææ§ããããšæããŸãããïŒ
æããã«ãããã«ã¯å²ãåœãŠãçºçããŸãããäŸå€ãã¹ããŒããããã¯ãŸãã ãšæãããŸãã
ã¯ãã ãããå²ãåœãŠãåŒãèµ·ãããªãã®ã¯çŽ æŽãããããšã§ãã
System.ValueTupleãã€ã³ã¹ããŒã«ããããã«ãŠãŒã¶ãŒã«æ瀺ã§ããªãçç±ã¯ãããŸããïŒ
ããã¯ãValueTupleã¢ãããŒããçæããå Žåã®åäœã«ãªããŸãã ãã ããç¹°ãè¿ãã«ãªããŸããããŠãŒã¶ãŒãã³ãŒãã®æ§é ãå€§å¹ ã«å€æŽããããšãªãããŠãŒã¶ãŒãçŸåšã³ãŒããæ§é åããŠããæ¹æ³ã«é©åããåªãããã®ãçæã§ããã°äŸ¿å©ã§ãã
VBãŠãŒã¶ãŒã¯ãã®åé¡ã«åççãªæ¹æ³ã§å¯ŸåŠããæ¹æ³ãæã£ãŠããå¿ èŠãããããã§ã:)ãããããã®ãããªã¢ãããŒãã¯ç§ã«ã¯ããããŸãã:)
@CyrusNajmabadi ããŠãŒã¶ãŒã®ã³ãŒãã§ç¬èªã®ããã·ã¥èšç®ãè¡ãå¿ èŠãããå Žåã¯ãããŒãã«ã«ãã¯ã¢ãããšXORã®çµã¿åããã§ããããCRC32ãæ©èœããå¯èœæ§ããããŸãïŒãã ãããªãŒããŒãããŒããå¯èœæ§ã®ããç®è¡æŒç®ã¯æ©èœããŸããïŒã ãã ããããã€ãã®æ¬ ç¹ããããŸãã
ãŸã è¡ã£ãŠããªãå Žåã¯ãHashCodeã¿ã€ããæ€åºããå¯èœãªå Žåã¯ããã䜿çšã§ããããšãé¡ã£ãŠããŸããXXHashã®æ¹ãã¯ããã«åªããŠããã¯ãã ããã§ãã
@morganbrhttps ïŒ //github.com/dotnet/roslyn/pull/24161ãåç §ããŠãã ãã
ç§ãã¡ã¯ä»¥äžãè¡ããŸãïŒ
Return (a, b, c, ...).GetHashCode()
çæããŸãæ¬åœã«æ®å¿µãªã®ã¯ã3Dãã§ãã åºæ¬çã«ãVBã䜿çšããŠããããValueTupleãŸãã¯æè¿ã®ã·ã¹ãã ã䜿çšããŠããªã人ã¯ããããã®ããã«çæãããåççãªããã·ã¥ã¢ã«ãŽãªãºã ãååŸããããã«ç§ãã¡ã䜿çšããããšã¯ã§ããŸããã
ã³ãŒãã®ã©ããã«256ãšã³ããªã®ã«ãã¯ã¢ããããŒãã«ãé 眮ããå¿ èŠããããŸã
ããã¯å®å šã«å£ã«åããªãã§ããã:)
ããŒãã«çæã³ãŒããå£ã«åããªãã®ã§ããïŒ å°ãªããšããŠã£ãããã£ã¢ã®äŸã§ã¯ãã³ãŒãã¯ããã»ã©å€ããããŸããïŒãã ãããŠãŒã¶ãŒã®ãœãŒã¹ã®ã©ããã«ç§»åããå¿ èŠããããŸãïŒã
RoslynãïŒILã䜿çšããŠïŒåç §ããã¢ã»ã³ããªããå©çšã§ããªãå Žåã«ïŒã¯ããã«åçŽãªïŒã³ã³ãã€ã©å±æ§ã¯ã©ã¹å®çŸ©ã䜿çšããŠHashCodeãœãŒã¹ããããžã§ã¯ãã«è¿œå ããããšã¯ãã©ãã»ã©ã²ã©ãããšã§ããããïŒ
RoslynãïŒã¯ããã«åçŽãªïŒã³ã³ãã€ã©å±æ§ã¯ã©ã¹å®çŸ©ã§è¡ãããã«ãåç §ãããŠããã¢ã»ã³ããªããå©çšã§ããªãå Žåã«ãHashCodeãœãŒã¹ããããžã§ã¯ãã«è¿œå ããã®ã¯ã©ãã»ã©ã²ã©ãããšã§ããããïŒ
ãªãŒããŒãããŒèšç®ãVBã§æ©èœãããè¯ãæ¹æ³ããŸã£ãããªãããšã«é©ããŠããŸã:(
ãããã£ãŠãå°ãªããšãã2ã€ã®å€ãäžç·ã«ããã·ã¥ããŠããå Žåã§ãã次ã®ãã®ãäœæããå¿ èŠãããããã§ãã
`` `cïŒ
var hc1 =ïŒuintïŒïŒvalue1ïŒ.GetHashCodeïŒïŒ?? 0ïŒ; //ãªãŒããŒãããŒããå¯èœæ§ããããŸã
var hc2 =ïŒuintïŒïŒvalue2ïŒ.GetHashCodeïŒïŒ?? 0ïŒ; //ãªãŒããŒãããŒããå¯èœæ§ããããŸã
uint hash = MixEmptyState();
hash += 8; // can overflow
hash = QueueRound(hash, hc1);
hash = QueueRound(hash, hc2);
hash = MixFinal(hash);
return (int)hash; // can overflow
Note that this code already has 4 lines that can overflow. It also has two helper functions you need to call (i'm ignoring MixEmptyState as that seems more like a constant). MixFinal can *definitely* overflow:
```c#
private static uint MixFinal(uint hash)
{
hash ^= hash >> 15;
hash *= Prime2;
hash ^= hash >> 13;
hash *= Prime3;
hash ^= hash >> 16;
return hash;
}
QueueRoundãšåæ§ã«ïŒ
c#
private static uint QueueRound(uint hash, uint queuedValue)
{
hash += queuedValue * Prime3;
return Rol(hash, 17) * Prime4;
}
ã ããç§ã¯ãããã©ã®ããã«æ©èœããã®ãæ£çŽã«ããããŸãã:(
RoslynãïŒILã䜿çšããŠïŒïŒå€ãã®å ŽåïŒè¡ãããã«ãHashCodeãœãŒã¹ããããžã§ã¯ãã«è¿œå ããã®ã¯ã©ãã»ã©ã²ã©ãããšã§ããããã
ãããæ©èœããããšãã©ã®ããã«æ³åããŸããïŒ é¡§å®¢ã¯äœãæžããã³ã³ãã€ã©ã¯ããã«å¿ããŠäœãããŸããïŒ
ãŸããããããã¹ãŠã«å¯ŸåŠããã®ã¯ããªãŒããŒãããŒãªãã§uintããint32ïŒããã³ãã®éïŒã«å€æãããããªãã¯ãã«ããŒã.Netã«æ¢ã«å ¬éãããŠããå Žåã§ãã
ãããã¯ååšããŸããïŒ ãããããªããç§ã¯ç°¡åã«VBããŒãžã§ã³ãæžãããšãã§ãããªãŒããŒãããŒããããšãªãã¿ã€ãéãè¡ãæ¥ããå¿ èŠãããç¶æ³ã«ãããã䜿çšããã ãã§ãã
ããŒãã«çæã³ãŒããå£ã«åããªãã®ã§ããïŒ
ããæããŸãã ã€ãŸããããã顧客ã®èŠ³ç¹ããèããŠãã ããã 圌ãã¯ãããŸãèªå·±å®çµãã劥åœãªçµæããããããŸãšããªGetHashCodeã¡ãœãããæãã§ããŸãã ãã®æ©èœãå®è¡ããŠãè£å©çãªããããã§ã³ãŒããè¥å€§åãããããšã¯ãããªãäžå¿«ãªããšã«ãªãã§ãããã ãŸããCïŒã®ãšã¯ã¹ããªãšã³ã¹ãåé¡ãªãããšãèãããšãããªãæªãããšã§ãã
笊å·ä»ããšç¬Šå·ãªãã®64ãããåã®çµã¿åãããšã®éã§ãã£ã¹ãããããšã«ãããããããæ£ãããªãŒããŒãããŒåäœãåŸãããšãã§ããå ŽåããããŸãã ãã®ãããªãã®ïŒãã¹ããããŠããããVBãã£ã¹ãæ§æãããããŸããïŒïŒ
Dim hashCode = -252780983
hashCode = (Int32)((Int32)((Unt64)hashCode * -1521134295) + (UInt64)i.GetHashCode())
次ã®ãã®ããªãŒããŒãããŒããªãããšãã©ã®ããã«ç¥ã£ãŠããŸããïŒ
c#
(Int32)((Unt64)hashCode * -1521134295)
ãããšãããã®åé¡ã®æçµïŒint32ïŒãã£ã¹ãã§ããïŒ
ãªãŒããŒãããŒãã§ãã¯ãããconvæäœã䜿çšããããšã«æ°ã¥ããŠããŸããã§ããã ãã£ã¹ãããåã«32ããããŸã§ãã¹ã¯ã§ãããšæããŸãã
(Int32)(((Unt64)hashCode * -1521134295) & 0xFFFFFFFF)
uint32.Maxã®å€ãInt32ãžã®å€ææã«ãªãŒããŒãããŒããããããããã31ããã:)
ããã¯å¯èœã§ãã éã...ãããå¯èœã§ã:)ãã®ã³ãŒãã«ã¯ããããã®ãã£ã¹ãããããŸãã
Okã ç§ã¯å®è¡å¯èœãªè§£æ±ºçããããšæããŸãã ä»æ¥çæããã¢ã«ãŽãªãºã ã®äžæ žã¯æ¬¡ã®ãšããã§ãã
c#
hashCode = hashCode * -1521134295 + j.GetHashCode();
64ãããã®èšç®ãè¡ã£ãŠãããããhashCodeãã¯32ãããã«å¶éãããŠãããšããŸãããã ãã®å Žåã <largest_32_bit> * -1521134295 + <largest_32_bit>
ã¯64ãããããªãŒããŒãããŒããŸããã ãããã£ãŠãåžžã«64ãããã§èšç®ãå®è¡ããŠããã32ïŒãŸãã¯32ãããïŒã«ã¯ã©ã³ãããŠã³ããŠã次ã®ã©ãŠã³ãããªãŒããŒãããŒããªãããã«ããããšãã§ããŸãã
ããããšãïŒ
@ MaStr11 @morganbr @sharwellãšèª°ããããã ã³ãŒããæŽæ°ããŠãVBçšã«ä»¥äžãçæããŸããã
Dim hashCode As Long = 2118541809
hashCode = (hashCode * -1521134295 + a.GetHashCode()) And Integer.MaxValue
hashCode = (hashCode * -1521134295 + b.GetHashCode()) And Integer.MaxValue
Return CType(hashCode And Integer.MaxValue, Integer)
誰ããç§ãæ£æ°ã«ãã§ãã¯ããŠããããçã«ããªã£ãŠããŠããã§ãã¯ã¢ãŒãããªã³ã«ãªã£ãŠããŠããªãŒããŒãããŒããŠã¯ãªããªãããšã確èªã§ããŸããïŒ
@CyrusNajmabadi ããªãŒããŒãããŒããŸããïŒInt64.Max = Int32.Max * Int32.Maxã§ãããå®æ°ããããããã¯ããã«å°ããããïŒããäžäœãããããŒãã«ãã¹ã¯ããŠããããã31ãããããã·ã¥ã®ã¿ã§ãã äžäœãããããªã³ã®ãŸãŸã«ããŠãããšããªãŒããŒãããŒãšèŠãªãããŸããïŒ
@CyrusNajmabadi hashCode
ã¯Long
ã§ã0ããInteger.MaxValue
ãŸãã ãªãç§ã¯ãããæã«å
¥ããŠããã®ã§ããïŒ
ããããããããå®éã«ã¯ãªãŒããŒãããŒããããšã¯ã§ããŸããã
ãšããã§ã次åã®ããã·ã¥ãè¿œå ããããããRoslynã«NuGetããã±ãŒãžãè¿œå ããŠããããããšæããŸãã
ãã ããäžäœãããããŒãã«ãã¹ã¯ããŠããããã31ãããã®ããã·ã¥ã«ãããŸããã äžäœãããããªã³ã®ãŸãŸã«ããŠãããšããªãŒããŒãããŒãšèŠãªãããŸããïŒ
ããã¯è¯ãç¹ã§ãã ç§ã¯uintsã䜿çšããŠããå¥ã®ã¢ã«ãŽãªãºã ã«ã€ããŠèããŠãããšæããŸãã ãããã£ãŠãlongããuintã«å®å šã«å€æããããã«ã笊å·ããããå«ããå¿ èŠã¯ãããŸããã§ããã ãã ããããã¯ãã¹ãŠç¬Šå·ä»ãã®èšç®ã§ããããã0xffffffffã«å¯ŸããŠãã¹ã¯ããã ãã§ãåãšã³ããªãè¿œå ããåŸã«äžäœ32ãããã®ã¿ãä¿æããããã«ãããšåé¡ãªããšæããŸãã
æé©ã§ã¯ãªãããã·ã¥ãè¿œå ããããããRoslynã«NuGetããã±ãŒãžãè¿œå ããŠãããããã§ãã
ãŠãŒã¶ãŒã¯ãå¿ èŠã«å¿ããŠãã§ã«ãããè¡ãããšãã§ããŸãã ããã¯ããŠãŒã¶ãŒããããã®äŸåé¢ä¿ãè¿œå ããªãããŸãã¯è¿œå ã§ããªãå Žåã®å¯ŸåŠæ¹æ³ã§ãã ããã¯ããŠãŒã¶ãŒã«é©åºŠã«ãååã«è¯ããããã·ã¥ãæäŸããããšã§ããããŸãã ã€ãŸãã人ã ãããæ¡çšããäžè¬çãªãx + y + zãã¢ãããŒããããåªãããã®ã§ãã ãã¹ãŠã®ãŠãŒã¶ãŒã®ããã·ã¥ã«é¢ããŠãæé©ããšã¯äœãã«ã€ããŠã®é©åãªå®çŸ©ããªãããããæé©ãã§ããããšãæå³ããŠããŸããã ããã§æ¡çšããŠããã¢ãããŒãã¯ãå¿ååã®ã³ã³ãã€ã©ãŒã«ãã£ãŠãã§ã«ãªãªãŒã¹ãããŠããã¢ãããŒãã§ããããšã«æ³šæããŠãã ããã ãŠãŒã¶ãŒã®ã³ãŒãã«å€§éã®è€éããè¿œå ããããšãªããé©åºŠã«è¯å¥œãªåäœã瀺ããŸãã æéã®çµéãšãšãã«ããŸããŸãå€ãã®ãŠãŒã¶ãŒãåé²ã§ããããã«ãªããšããã®ãããªãŠãŒã¶ãŒã¯ãã£ãããšæ¶ããŠãã»ãšãã©ã®äººã«ãšã£ãŠHashCode.Combineã«çœ®ãæããããå¯èœæ§ããããŸãã
ã ããç§ã¯ããã§å°ãåããç§ããã¹ãŠã®æžå¿µã«å¯ŸåŠãããšæã次ã®ããšãæãã€ããïŒ
Dim hashCode As Long = 2118541809
hashCode = (hashCode * -1521134295 + a.GetHashCode()).GetHashCode()
hashCode = (hashCode * -1521134295 + b.GetHashCode()).GetHashCode()
Return CType(hashCode, Integer)
èå³æ·±ãã®ã¯ã (hashCode * -1521134295 + a.GetHashCode())
ã«ãã£ãŠçæãããint64å€ã§.GetHashCode()
ãå
·äœçã«åŒã³åºãããšã§ãã ãã®64ãããå€ã§.GetHashCodeãåŒã³åºããšãããŒãºã«åã£ã2ã€ã®åªããããããã£ããããŸãã ãŸããhashCodeãæ£åœãªint32å€ã®ã¿ãæ ŒçŽããããã«ããŸãïŒããã«ãããæçµçã«è¿ããããã£ã¹ããåžžã«å®å
šã«å®è¡ã§ããŸãïŒã 次ã«ã䜿çšããŠããint64tempå€ã®äžäœ32ãããã®è²Žéãªæ
å ±ã倱ãããªãããã«ããŸãã
@CyrusNajmabadiå®éã«ããã±ãŒãžãã€ã³ã¹ããŒã«ããããšãç³ãåºãããšã¯ç§ãæ±ããŠãããã®ã§ãã ãããããå¿ èŠããç§ãæããŸãã
HashCodeãšå ¥åããå ŽåãSystem.HashCodeãMS nugetããã±ãŒãžã§æäŸãããŠãããšãRoslynããããæäŸããŸãã
ååšããªãGetHashCodeãªãŒããŒããŒããçæããåãæäœã§ããã±ãŒãžãã€ã³ã¹ããŒã«ããå¿ èŠããããŸãã
ã»ãšãã©ã®ãŠãŒã¶ãŒã«ãšã£ãŠãããã¯é©åãªéžæã§ã¯ãªããšæããŸãã äŸåé¢ä¿ã®è¿œå ã¯ããŠãŒã¶ãŒã«åŒ·å¶ãããã¹ãã§ã¯ãªãéåžžã«éãæäœã§ãã ãŠãŒã¶ãŒã¯ãããã®éžæãè¡ãé©åãªææã決å®ã§ããIDEã¯ãããå°éããŸãã ããã¯ããããŸã§ãã¹ãŠã®æ©èœã§æ¡çšããŠããã¢ãããŒãã§ããã人ã ã奜ãããã«èŠããå¥å šãªã¢ãããŒãã§ãã
泚ïŒåç §ãè¿œå ããããã«ããã®APIã¯ã©ã®nugetããã±ãŒãžã«å«ãŸããŠããŸããïŒ
å®è£ ã¯System.Private.CoreLib.dllã«ãããããã©ã³ã¿ã€ã ããã±ãŒãžã®äžéšãšããŠæäŸãããŸãã ã³ã³ãã©ã¯ãã¯System.Runtime.dllã§ãã
Okã ãã®å ŽåããŠãŒã¶ãŒãããæ°ããã¿ãŒã²ãããã¬ãŒã ã¯ãŒã¯ã«ç§»è¡ããå Žåã«ããããååŸããããã«æãããŸãã ãã®ãããªããšã¯ããŠãŒã¶ãŒã®ãããžã§ã¯ãã«å¯ŸããŠãequals + hashcodeã®çæããå®è¡ãããã¹ãããã§ã¯ãããŸããã
æãåèã«ãªãã³ã¡ã³ã
決å®
AddRange
ã¡ãœãããåé€ããå¿ èŠããããŸãã é åãé »ç¹ã«è¡šç€ºãããå¯èœæ§ã¯ã»ãšãã©ãããŸããã ãããŠããã倧ããªé åãå«ãŸãããšãåé¡ã¯èšç®ããã£ãã·ã¥ããå¿ èŠããããã©ããã§ãã åŒã³åºãåŽã§forã«ãŒããèŠããšãããã«ã€ããŠèããå¿ èŠãããããšãæããã«ãªããŸããIEnumerable
ãªãŒããŒããŒããAddRange
ã«è¿œå ããããªãã®string
ãšStringComparison
ãå¿ èŠãšããAdd
ãžã®ãªãŒããŒããŒãã¯å¿ èŠãªããšæããŸãã ã¯ããIEqualityComparer
ãä»ããŠåŒã³åºããããå¹ççã§ããå¯èœæ§ããããŸãããåŸã§ä¿®æ£ã§ããŸããGetHashCode
ããšã©ãŒã§å»æ¢ããããã®ãšããŠããŒã¯ããã®ã¯è¯ãèãã§ãããããã«äžæ©é²ãã§IntelliSenseããé ããŸããããã«ããã次ã®ããšãå¯èœã«ãªããŸãã
`` `CïŒïŒT1å€1ïŒ;ïŒT1å€1ãT2å€2ïŒ;ïŒT1å€1ãT2å€2ãT3å€3ïŒ;ïŒT1å€1ãT2å€2ãT3å€3ãT4å€4ïŒ;ïŒT1å€1ãT2å€2ãT3å€3ãT4å€4ãT5å€5ïŒ;ïŒT1å€1ãT2å€2ãT3å€3ãT4å€4ãT5å€5ãT6å€6ïŒ;ïŒT1å€1ãT2å€2ãT3å€3ãT4å€4ãT5å€5ãT6å€6ãT7å€7ïŒ;ïŒT1å€1ãT2å€2ãT3å€3ãT4å€4ãT5å€5ãT6å€6ãT7å€7ãT8å€8ïŒ;
//ã³ã¢ã¢ã»ã³ããªã«ååšããŸã
// .NET FrameworkïŒmscorlib
// .NET CoreïŒSystem.Runtime / System.Private.CoreLib
åå空éã·ã¹ãã
{{
public struct HashCode
{{
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public static int Combine
public static int Combine
}
`` `