é·ãè°è«ã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()
ã䜿ãããšã«é Œãããšãã
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
ã¢ã«ãŽãªãºã ã䜿çšããå¿
èŠããããŸãã
è¿
éã§æ±ããã®ãå¿
èŠãªå Žåã¯ã ValueTuple.Create(field1, field2).GetHashCode()
䜿çšã§ããŸãã ããã¯ã Tuple
ã§äœ¿çšãããŠãããã®ãšåãã¢ã«ãŽãªãºã ã§ããïŒããã«èšãã°ã Objects
ã¢ã«ãŽãªãºã ãšäŒŒãŠããŸãïŒãå²ãåœãŠã®ãªãŒããŒãããã¯ãããŸããã
ãã以å€ã®å Žåã¯ãå¿ èŠãªããã·ã¥ã®è¯ãããã£ãŒã«ãå€ã®å¯èœæ§ïŒã©ã®ã¢ã«ãŽãªãºã ãè¯ãçµæãŸãã¯æªãçµæããããããã«åœ±é¿ããïŒãhashDoSæ»æã®å¯èœæ§ããã€ããªãæ³ãšããŠè¡çªãè¡ããã©ããã«ã€ããŠè³ªåããããŸã-å¶æ°ãå·ã€ãïŒãã€ããªã®å Žåãšåæ§ã«ãããã·ã¥ããŒãã«ãåæ§ïŒãªã©ã1ã€ã®é©åããã¹ãŠé©çšã§ããªããªããŸãã
@JonHannaãããã®è³ªåã¯ãããšãã°string.GetHashCode()
ãåœãŠã¯ãŸããšæããŸãã Hash
ãæäŸããããšãããããé£ããçç±ãããããŸããã
å®éã«ã¯ãç¹å¥ãªèŠä»¶ãæã€ãŠãŒã¶ãŒã¯Hash
䜿çšãç°¡åã«åæ¢ã§ãããããããåçŽãªã¯ãã§ããã string.GetHashCode()
䜿çšãåæ¢ããã®ã¯å°é£ã§ãã
+1
ASP.NETã httpsïŒ//github.com/aspnet/Common/blob/dev/src/Microsoft.Extensions.HashCodeCombiner.Sources/HashCodeCombiner.csã«ãããã®1ã€ããã
è¿ éã§æ±ããã®ãå¿ èŠãªå Žåã¯ã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
ã®å®éã®ã³ãŒãã§ã
ã§ã¯ãããã§äœãèŠãããšãã§ããŸããïŒ æåã«ã¹ã¿ãã¯ã«æ§é äœãäœæãã次ã«å®éã®ããã·ã¥ã³ãŒããåŒã³åºããŸãã
ããã§ã HashHelper.Combine
ã®äœ¿çšãšæ¯èŒããŸããããã¯ãããããç®çã§ã Hash.Combine
å®éã®å®è£
ã§ããå¯èœæ§ããããŸãã
ç¥ã£ãŠããïŒïŒïŒ
ããããããã§æ¢ãŸããªãã§ãã ãã...å®éã®ãã©ã¡ãŒã¿ã䜿çšããŸãããïŒ
[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));
}
è¯ãããšã§ãããããã¯éåžžã«å®å®ããŠããŸãã ãããããããå¥ã®æ¹æ³ãšæ¯èŒããŠã¿ãŸãããã
ãããè¹å€ã«åºãŸããã...
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);
}
ãããŠçµæã¯ããªãäŸç€ºçã§ã
JITãåŒã³åºãã«å¯ŸããŠçæããå®éã®ã³ãŒããå®éã«æ€æ»ããããšã¯ã§ããŸããããããããŒã°ãšãšãããŒã°ã ãã§ãææ¡ãå«ããããšãæ£åœåã§ããŸãã
åæã®èŠç¹ã¯åçŽã§ããä¿æã¿ã€ãã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
ã䜿çšããŸãã
ç§ãã¡ã¯ããã«ã€ããŠããå°ãè°è«ããŸããããããŠããªãã¯ç§ãã¡ãçŽåŸãããŸãã:-)
ããã«ããã€ãã®è³ªåïŒ
System.Numerics
ã¯æ©èœããå¯èœæ§ããããŸãã System.Collections.Generic
ãæ©èœããå¯èœæ§ããããŸããããã¯ãæ¯èŒæ©èœããããã³ã¬ã¯ã·ã§ã³ã®ã³ã³ããã¹ãã§ããã·ã¥ãæãé »ç¹ã«äœ¿çšãããããã§ããïŒ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)
ãæžãããšã¯ååã«ç°¡åã§ããHashCode
ã¿ã€ããçšæããå¿
èŠããããŸãã Int64HashCode
ããŸãã¯LongHashCode
ãç§ã¯TryRoslynã§ç©äºã®å°ããªãµã³ãã«å®è£ ãäœæããŸããïŒ http ïŒ//tinyurl.com/zej9yux
幞ããªããšã«ã確èªã¯ç°¡åã§ãã ãããŠãè¯ããã¥ãŒã¹ã¯ãããããã®ãŸãŸæ£ããæ©èœããããšã§ãð
人ã ãæåŸã®.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
[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èãïŒ
Create<T>
ãã¡ã¯ããªã¡ãœãããåé€ããå¿
èŠããããŸãã ããã§ãªããã°ãåããã®ãæžã2ã€ã®æ¹æ³ã HashCode.Create(_val)
ãŸãã¯new HashCode().Combine(_val)
ãŸãã ãŸãã Create
/ Combine
ç°ãªãååãä»ãããšãæ°ããæåã®ãã£ãŒã«ããè¿œå ããå Žåã«2è¡ãå€æŽããå¿
èŠããããããå·®åã«é©ããŠããŸãããHashCode
ã¯æååãšã¯äœã®é¢ä¿ããããŸããã 代ããã«ãæååã«GetHashCode(StringComparison)
apiãè¿œå ããå¿
èŠããããŸããïŒ ïŒãŸãããããã¯ãã¹ãŠåºæ°ã®æ¯èŒã§ãããããã¯string.GetHashCode
ã®ããã©ã«ãã®åäœã§ããïŒint
å€æããããã®æé»ã®æŒç®åããã§ã«ååšããå Žåã Value
ã䜿çšããæå³ã¯äœã§ããïŒ ç¹°ãè¿ããŸãããããã¯ããŸããŸãªäººã
ãããŸããŸãªããšãæžãããšã«ã€ãªãããŸããlong
ãªãŒããŒããŒããæ°ããã¿ã€ãã«ç§»åããå¿
èŠããããŸãã HashCode
ã¯32ãããå¹
ã®ã¿ã«ãªããŸãã é·ãã¯åãŸããŸããããããç§ã®ææ¡ãã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
[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ãããã䜿çšãããã¡ã€ã³ã¯éåžžã«å¶éãããŠããïŒã»ãšãã©ã¯ãã§ã«ãã¬ãŒã ã¯ãŒã¯èªäœã§ã«ããŒãããŠããŸãïŒãæ®ãã¯éãæªãã§ãã
ãŸãã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
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ïŒã¯ãã³ãŒãã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ã®äžèŽã®ãã¡ãæåã®æ°ããŒãžããã§ããã»ãšãã©ãã¹ãŠã®ãŠãŒã¹ã±ãŒã¹ã«æååããããããã€ãã®ã±ãŒã¹ã§ã¯ãããŸããŸãªçš®é¡ã®æååæ¯èŒã䜿çšããŸãã
ïŒãããŠä»ã®äœåããïŒ
ãããã£ãŠã確ãã«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ã€ã®ããšãå®çŸããŸãã
ãŸããäžèšã®æ¡åŒµã¡ãœãã@Eilonã®ãããªäžè¬çãªãã€ã©ãŒãã¬ãŒããã«ããŒã¯è¯ãããšã§ã¯ãªããæªãããšã§ããããšãèæ ®ããå¿ èŠããããŸãã ãã«ããŒã¡ãœããã®ã³ããŒãšè²Œãä»ãã«äœæéãç¡é§ã«ãªããé©åã«å®è¡ãããªããšãäžèŠãªã³ãŒãã®èšåŒµããã°ãçºçããå¯èœæ§ããããŸãã
ãã ããäž»ãªé¢å¿äºãç¹å¥ãªã±ãŒã·ã³ã°string
ã«é¢ãããã®ã§ããå Žåãããã¯ã©ãã§ããããã
`` `CïŒ
public struct HashCodeïŒIEquatable
{{
public HashCode Combine
}
// 䜿çšæ³
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
public static HashCodeValue Combine
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ã€ã®æžå¿µäºé ããããŸãã
Hash
ãšHashCode
å Žåãã©ã¡ãããå§ããŸããïŒ ãããã®ååããã¯æããã§ã¯ãããŸããã LinkedList<T>
ãšLinkedListNode<T>
ãããšãã©ã¡ããã¡ã€ã³ã®ãšã³ããªãã€ã³ãã§ãããã LinkedList<T>
ã§ãããã©ã¡ãããã«ããŒã§ããããæ確ã«ãªããŸãã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
public static HashCode Create
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 \ã®å®è£
ãå¿
èŠãšããçç±
@jamesqo ãç§ã¯ãããäžå€ã«ä¿ã€æ¹ãè¯ãããšã«åæããŸãïŒIEnumerableã§ã¯ãããŸãã\
@mellinoeããã«ãããåçŽãªã±ãŒã¹ãå°ãåçŽã«ãªããšæããŸããããã以äžã®ããšã¯ããã«è€éã«ãªããŸãïŒãããŠãäœãããã®ãæ£ãããã«ã€ããŠã¯ããŸãæ確ã§ã¯ãããŸããïŒã
ããã«ã¯ä»¥äžãå«ãŸããŸãïŒ
ãã®ãããã¯ã«ã€ããŠä»¥åã«æçš¿ããã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ã«æºæ ããŠããŸããã
æãåèã«ãªãã³ã¡ã³ã
ããã@KrzysztofCwalinaãšç§ã䜿çšããçè«çæ ¹æ ã§ããã 売ãåããŸããïŒ