๊ธด ํ ๋ก ์ 200๊ฐ ์ด์์ ๋๊ธ๋ก ๋์ฒดํ์ฌ ์๋ก์ด ๋ฌธ์ dotnet/corefx#14354
์ด ๋ฌธ์ ๋ ์ข ๋ฃ๋์์ต๋๋ค !!!
Java์๋ ๊ตฌ์ฑ ํ๋์ ํด์ ์ฝ๋๋ฅผ ๋น ๋ฅด๊ฒ ๊ฒฐํฉํ์ฌ Object.hashCode()
๋ก ๋ฐํํ๊ธฐ ์ํ Objects.hash
๊ฐ ์์ต๋๋ค. ๋ถํํ๊ฒ๋, .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.Combine(ํด์));
var hashCode3 = HashCode.Empty;
foreach(ํด์์์ int ํด์) { hashCode3 = hashCode3.Combine(hash); }
(int)ํด์์ฝ๋3;
```
๊ตฌํ์ HashHelpers
์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
๋น ๋ฅด๊ณ ๋๋ฌ์ด ๊ฒ์ ์ํ๋ฉด ValueTuple.Create(field1, field2).GetHashCode()
์ฌ์ฉํ ์ ์์ต๋๋ค. Tuple
์์ ์ฌ์ฉ๋ ๊ฒ๊ณผ ๋์ผํ ์๊ณ ๋ฆฌ์ฆ์ด๋ฉฐ(์ด ์ ์ ์์ด์๋ Objects
์์์ ์ ์ฌํจ) ํ ๋น ์ค๋ฒํค๋๊ฐ ์์ต๋๋ค.
๊ทธ๋ ์ง ์์ผ๋ฉด ์ผ๋ง๋ ์ข์ ํด์๊ฐ ํ์ํ์ง, ํ๋ ๊ฐ์ด ์ด๋ค ๊ฐ๋ฅ์ฑ์ด ์๋์ง(์ด๋ค ์๊ณ ๋ฆฌ์ฆ์ด ์ข์ ๊ฒฐ๊ณผ ๋๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ์ค ๊ฒ์ธ์ง์ ์ํฅ์ ๋ฏธ์นจ), hashDoS ๊ณต๊ฒฉ์ ๊ฐ๋ฅ์ฑ์ด ์๋์ง, ๋ชจ๋๋ก ์ถฉ๋์ ์ํํ๋์ง์ ๋ํ ์ง๋ฌธ์ด ์์ต๋๋ค. ์ง์ ํด์ฌ(์ด์ง ์ง์ ํด์ ํ ์ด๋ธ์์์ ๊ฐ์ด) ๋ฑ์ผ๋ก ์ธํด ๋ง๋ฅ์ด ์ ์ฉ๋์ง ์์ต๋๋ค.
@JonHanna ๋๋ ๊ทธ ์ง๋ฌธ์ด ์๋ฅผ ๋ค์ด string.GetHashCode()
์๋ ์ ์ฉ ๋๋ค๊ณ ์๊ฐํฉ๋๋ค. Hash
์ ๊ณตํ๋ ๊ฒ์ด ๊ทธ๋ณด๋ค ๋ ์ด๋ ค์ด ์ด์ ๋ฅผ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
์ฌ์ค ํน๋ณํ ์๊ตฌ ์ฌํญ์ ๊ฐ์ง ์ฌ์ฉ์๋ Hash
์ฌ์ฉ์ ์ฝ๊ฒ ์ค๋จํ ์ ์์ง๋ง string.GetHashCode()
์ฌ์ฉ์ ์ค๋จํ๋ ๊ฒ์ด ๋ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ๋ ๊ฐ๋จํด์ผ ํฉ๋๋ค.
+1
ASP.NET์๋ https://github.com/aspnet/Common/blob/dev/src/Microsoft.Extensions.HashCodeCombiner.Sources/HashCodeCombiner.cs ์ค ํ๋๊ฐ
๋น ๋ฅด๊ณ ๋๋ฌ์ด ๊ฒ์ ์ํ๋ฉด ValueTuple.Create(field1, field2).GetHashCode()๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์, ์ข์ ์๊ฐ์ด๊ตฐ์. ์ด ๊ธ์ ์์ฑํ ๋ ValueTuple
์๊ฐํ์ง ๋ชปํ์ต๋๋ค. ๋ถํํ๋ ๋๋ ๊ทธ๊ฒ์ด C# 7/๋ค์ ํ๋ ์์ํฌ ๋ฆด๋ฆฌ์ค๊น์ง ์ฌ์ฉ ๊ฐ๋ฅํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ด ๊ทธ ์ฑ๋ฅ์ด ๋ ๊ฒ์ธ์ง์กฐ์ฐจ ์ ์ ์์ต๋๋ค( EqualityComparer
์์ฑ/๋ฉ์๋ ํธ์ถ ์ ํฉ์ฐ๋ ์ ์์). ๊ทธ๋ฌ๋ ๋๋ ์ด๊ฒ์ ์ธก์ ํ๊ธฐ ์ํด ์ด๋ค ๋ฒค์น๋งํฌ๋ ์ทจํ์ง ์์๊ธฐ ๋๋ฌธ์ ๋๋ ์ ๋ง๋ก ์์ง ๋ชปํ ๊ฒ์
๋๋ค. ์ฌ๋๋ค์ด ํํ์ ํดํน ํด๊ฒฐ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉํ์ง ์๊ณ ์ฌ์ฉํ ์ ์๋ ํด์ฑ ์ ์ฉ/๋จ์ ํด๋์ค๊ฐ ์์ด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ทธ๋ ์ง ์์ผ๋ฉด ์ผ๋ง๋ ์ข์ ํด์๊ฐ ํ์ํ์ง, ํ๋ ๊ฐ์ด ์ด๋ค ๊ฐ๋ฅ์ฑ์ด ์๋์ง(์ด๋ค ์๊ณ ๋ฆฌ์ฆ์ด ์ข์ ๊ฒฐ๊ณผ ๋๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ์ค ๊ฒ์ธ์ง์ ์ํฅ์ ๋ฏธ์นจ), hashDoS ๊ณต๊ฒฉ์ ๊ฐ๋ฅ์ฑ์ด ์๋์ง, ๋ชจ๋๋ก ์ถฉ๋์ ์ํํ๋์ง์ ๋ํ ์ง๋ฌธ์ด ์์ต๋๋ค. ์ง์ ํด์ฌ(์ด์ง ์ง์ ํด์ ํ ์ด๋ธ์์์ ๊ฐ์ด) ๋ฑ์ผ๋ก ์ธํด ๋ง๋ฅ์ด ์ ์ฉ๋์ง ์์ต๋๋ค.
์ ๋์ ์ผ๋ก ๋์ํ์ง๋ง ๋๋ถ๋ถ์ ๊ตฌํ์ด ์ด๋ฅผ ๊ณ ๋ คํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ์๋ฅผ ๋ค์ด ArraySegment
์ ํ์ฌ ๊ตฌํ ์ ๋งค์ฐ ์์งํฉ๋๋ค. ์ด ํด๋์ค์ ์ฃผ์ ๋ชฉ์ ์ (ํ ๋น์ ํผํ๋ ๊ฒ๊ณผ ํจ๊ป) ํด์ฑ์ ๋ํด ์ ๋ชจ๋ฅด๋ ์ฌ๋๋ค ์ด ์ด์ ๊ฐ์ ์ด๋ฆฌ์์ ์ผ์ ํ๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด go-to ๊ตฌํ์ ์ ๊ณตํ๋ ๊ฒ์
๋๋ค. ๊ทํ๊ฐ ์ค๋ช
ํ ์ํฉ์ ์ฒ๋ฆฌํด์ผ ํ๋ ์ฌ๋๋ค์ ์์ ์ ํด์ฑ ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํ ์ ์์ต๋๋ค.
๋ถํํ๋ 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๋นํธ๋ก ๋ค์ด์ํ๋งํด์ผ ํ์ต๋๋ค. ์ต์ ํ๋ ํจ์์ ๋ฐฐ์ด์ ๊ฐ๋ ๊ฒ์ ๊ฐ๋ฐ์๊ฐ ์ต์ ํ๋์ง ์์๊ฑฐ๋ ๋ฒ๊ทธ๊ฐ ์๋ ํจ์๋ฅผ ์์ฑํ๋ ๊ฒ์ ํผํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ์ ํ ํ์์ ๋ฐ๋ผ ์ ํํ ์ ์์ต๋๋ค.
๊ด์ฌ์ด ์๋ ๊ฒฝ์ฐ ๊ตฌํ์ ๊ธฐ๊บผ์ด ๊ธฐ๋ถํ์ฌ ์ ๋ฌธ๊ฐ๊ฐ ๊ฒํ ํ๊ณ ์ต์ ํํ ์ ์์ต๋๋ค.
@redknightlois ๊ทธ๋ฐ ๋ ธ๋ ฅ์ ๋ด SpookyHash ๊ตฌํ์ ์ถ๊ฐํ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค.
@svick string.GetHashCode()์ ์ฃผ์ํ์ธ์. ํ์ง๋ง ์ด๋ ๋งค์ฐ ๊ตฌ์ฒด์ ์ ๋๋ค. ์์ฃผ ์ข์ ์ด์ ๋ Hash DoS ๊ณต๊ฒฉ์ ๋๋ค.
@terrajobst , API ๋ถ๋ฅ/๊ฒํ ๋๊ธฐ์ด์์ ์ด๊ฒ์ด ์ผ๋ง๋ ๋ฉ๋ฆฌ ์์ต๋๊น? ์ฐ๋ฆฌ๊ฐ ํญ์ ํ๋ซํผ์ ์ถ๊ฐํ๊ณ ์ถ์๋ ๋จ์ํ API๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ด์ ์ค์ ๋ก ์ด๋ฅผ ์ํํ๊ธฐ์ ์ถฉ๋ถํ ์๊ณ๋์ ๊ฐ๊ฒ ๋์์๊น์?
์ฐธ์กฐ: @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
์ ์ค์ ์ฝ๋์
๋๋ค.
์ด์ ์ฌ๊ธฐ์ ๋ฌด์์ ๋ณผ ์ ์์ต๋๊น? ๋จผ์ ์คํ์ ๊ตฌ์กฐ์ฒด๋ฅผ ๋ง๋ ๋ค์ ์ค์ ํด์ ์ฝ๋๋ฅผ ํธ์ถํฉ๋๋ค.
์ด์ Hash.Combine
์ ์ค์ ๊ตฌํ์ด ๋ ์ ์๋ HashHelper.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๊ฐ ์์ด์ผ ํ๋ค๋ ๋ง์ ์๋๋๋ค. ๊ตฌ์ฒด์ ์ธ ์๋๋ฆฌ์ค๊ฐ ์๋ ํ API๋ฅผ ์ค๊ณํ๋ ๊ฒ์ด ๋ ์ด๋ ต๋ค๋ ๋ง์ ํ๋ ๊ฒ๋ฟ์ ๋๋ค. "X์ ํ์ํ๋ฏ๋ก X๊ฐ ์ฌ์ฉํ ์ ์๋์ง ์ฌ๋ถ๊ฐ ์ฑ๊ณต์ ์ฒ๋"๋ผ๊ณ ๋งํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ ์๋ก์ด ์์ ์ ํ์ฉํ์ง ์๊ณ ๋์ผํ ์์ ์ ๋ณด๋ค ์ต์ ํ๋ ๋ฐฉ์์ผ๋ก ์ํํ๋ 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
๋ฅผ ํ๊ฐํ์ฌ ์์ ์ ์ฌ์ฉ ์ฌ๋ก์ ๋ง๋์ง ํ์ธํ ์ ์์ต๋๋ค. ํด์ฑ์ ๋ํด ์ ๋ชจ๋ฅด๋ ์ด๋ณด์๋ ์ ์ ํ ํด์๋ฅผ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ ๊ตฌ์ฑ ํ๋๋ฅผ xor-ing(๋๋ ๋ ๋์๊ฒ๋ ์ถ๊ฐ)ํ๋ ๋์ Hash.Combine
์ฌ์ฉํฉ๋๋ค.
์ฐ๋ฆฌ๋ ์ด๊ฒ์ ์กฐ๊ธ ๋ ๋ ผ์ํ๊ณ ๋น์ ์ ์ฐ๋ฆฌ๋ฅผ ํ์ ์์ผฐ์ต๋๋ค :-)
๋ช ๊ฐ์ง ์ถ๊ฐ ์ง๋ฌธ:
System.Numerics
๋ ์๋ํ ์ ์์ต๋๋ค. System.Collections.Generic
๋ ์๋ํ ์ ์์ต๋๋ค. ๋น๊ต์๊ฐ ์๊ณ ํด์ฑ์ด ์ปฌ๋ ์
์ปจํ
์คํธ์์ ๊ฐ์ฅ ์์ฃผ ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์
๋๋ค.(2) @Eilon ์ ๋ค์๊ณผ ๊ฐ์ด ๋งํ์ต๋๋ค.
์ฐธ๊ณ ๋ก ASP.NET Core(๋ฐ ๊ทธ ์ด์ ๋ฒ์ ๋ฐ ๊ด๋ จ ํ๋ก์ ํธ)๋ HashCodeCombiner๋ฅผ ์ฌ์ฉํฉ๋๋ค. https://github.com/aspnet/Common/blob/dev/src/Microsoft.Extensions.HashCodeCombiner.Sources/HashCodeCombiner.cs
( @David Fowler๋ ๋ช ๋ฌ ์ ์ GitHub ์ค๋ ๋์์ ์ธ๊ธํ์ต๋๋ค.)
๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ด ์ฌ์ฉ ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค https://github.com/aspnet/Mvc/blob/760c8f38678118734399c58c2dac981ea6e47046/src/Microsoft.AspNetCore.Mvc.Razor/Internal/ViewLocationCacheKey.cs#L129 -L144
``` C#
var hashCodeCombiner = HashCodeCombiner.Start();
hashCodeCombiner.Add(IsMainPage? 1:0);
hashCodeCombiner.Add(ViewName, StringComparer.Ordinal);
hashCodeCombiner.Add(์ปจํธ๋กค๋ฌ ์ด๋ฆ, StringComparer.Ordinal);
hashCodeCombiner.Add(AreaName, StringComparer.Ordinal);
if (ViewLocationExpanderValues โโ!= null)
{
foreach(ViewLocationExpanderValues์ var ํญ๋ชฉ)
{
hashCodeCombiner.Add(ํญ๋ชฉ.ํค, StringComparer.Ordinal);
hashCodeCombiner.Add(ํญ๋ชฉ.๊ฐ, 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๋ก ์ง์ ํด์ผ ํ ๊ฒ์ ๋๋ค.
์ฒซ ๋ฒ์งธ ๊ทผ์ฌ์น๋ก ๋ค์๊ณผ ๊ฐ์ด ์ ์ ๋ฐ ๋น๋๋ฅผ ๋จ์ผ ์ ํ์ผ๋ก ๊ฒฐํฉํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํ์ต๋๋ค.
``` C#
๋ค์์คํ์ด์ค System.Collections.Generic
{
๊ณต๊ฐ ๊ตฌ์กฐ์ฒด ํด์ ์ฝ๋
{
๊ณต๊ฐ ์ ์ ์ ์ ๊ฒฐํฉ(int ํด์1, ์ ์ ํด์2);
๊ณต๊ฐ ์ ์ ์ ์ ๊ฒฐํฉ(int ํด์1, ์ ์ ํด์2, ์ ์ ํด์3);
๊ณต๊ฐ ์ ์ ์ ์ ๊ฒฐํฉ(int ํด์1, ์ ์ ํด์2, ์ ์ ํด์3, ์ ์ ํด์4);
๊ณต๊ฐ ์ ์ ์ ์ ๊ฒฐํฉ(int ํด์1, ์ ์ ํด์2, ์ ์ ํด์3, ์ ์ ํด์4, ์ ์ ํด์5);
๊ณต๊ฐ ์ ์ ์ ์ ๊ฒฐํฉ(int ํด์1, ์ ์ ํด์2, ์ ์ ํด์3, ์ ์ ํด์4, ์ ์ ํด์5, ์ ์ ํด์6);
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 = ์๋ก์ด HashCode();
hashCode.Combine(IsMainPage? 1:0);
hashCode.Combine(๋ณด๊ธฐ ์ด๋ฆ, StringComparer.Ordinal);
hashCode.Combine(์ปจํธ๋กค๋ฌ ์ด๋ฆ, StringComparer.Ordinal);
hashCode.Combine(์์ญ ์ด๋ฆ, StringComparer.Ordinal);
if (ViewLocationExpanderValues โโ!= null)
{
foreach(ViewLocationExpanderValues์ var ํญ๋ชฉ)
{
hashCode.Combine(item.Key, StringComparer.Ordinal);
hashCode.Combine(ํญ๋ชฉ.๊ฐ, StringComparer.Ordinal);
}
}
ํด์ ์ฝ๋.๊ฐ์ ๋ฐํํฉ๋๋ค.
```
์๊ฐ?
๋๋ @jamesqo ์ ์ฐ์ ํธ์ถ์ ๋ํ ์์ด๋์ด๋ฅผ ์ข์ํฉ๋๋ค(์ธ์คํด์ค ๋ฉ์๋ Combine
์์ this
๋ฐํ).
์ ์ ๋ฉ์๋๋ฅผ ์์ ํ ์ ๊ฑฐํ๊ณ ์ธ์คํด์ค ๋ฉ์๋๋ง ์ ์งํ๋ ํ ...
Combine(long hashCode)
๋ int
์บ์คํ
๋ฉ๋๋ค. ์ฐ๋ฆฌ๊ฐ ์ง์ ์ผ๋ก ๊ทธ๊ฒ์ ์ํ๋๊ฐ?
long
์ค๋ฒ๋ก๋์ ์ฌ์ฉ ์ฌ๋ก๋ ๋ฌด์์
๋๊น?
@karelz ์ ๊ฑฐํ์ง ๋ง์ญ์์ค. ๊ตฌ์กฐ์ฒด๋ ๋ฌด๋ฃ๊ฐ ์๋๋๋ค. ํด์๋ ๋งค์ฐ ํซํ ๊ฒฝ๋ก์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ ์ ๋ฉ์๋๊ฐ ๋ณธ์ง์ ์ผ๋ก ๋ฌด๋ฃ์ผ ๋ ๋ช ๋ น์ ๋ญ๋นํ๊ณ ์ถ์ง๋ ์์ ๊ฒ์ ๋๋ค. ๋ด๊ฐ ๋๋ฌ์ธ๋ ๊ตฌ์กฐ์ฒด์ ์ค์ ์ํฅ์ ๋ณด์ฌ์ค ์ฝ๋ ๋ถ์์ ๋ณด์ญ์์ค.
์ด๋ฆ ์ถฉ๋์ ํผํ๊ธฐ ์ํด Hashing
์ ์ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ผ๋ฉฐ ์ฝ๋๊ฐ ์ข์ ๋ณด์
๋๋ค.
@redknightlois ํ๋์ int ํ๋๊ฐ ์๋ ์ผ๋ฐ ๊ตฌ์กฐ์ฒด๊ฐ ์๋ ๊ฒฝ์ฐ์๋ ๋์ผํ '๋์' ์ฝ๋๋ฅผ ์์ํด์ผ ํ๋์ง ๊ถ๊ธํฉ๋๋ค.
๊ทธ๊ฒ์ด ์ฌ์ ํ '๋์' ์ด์
๋ธ๋ฆฌ ์ฝ๋๋ผ๋ฉด ์ฌ๊ธฐ์์ ์ต์ ํ ์์
์ ๋ ์ ์ํํ๊ธฐ ์ํด JIT๋ฅผ ๊ฐ์ ํ ์ ์๋์ง ๊ถ๊ธํฉ๋๋ค. ๋ช ๊ฐ์ง ์ง์นจ์ ์ ์ฅํ๊ธฐ ์ํด API๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ์ตํ์ ์๋จ IMO๊ฐ ๋์ด์ผ ํฉ๋๋ค.
@redknightlois ๊ถ๊ธํฉ๋๋ค. ๊ตฌ์กฐ์ฒด(์ด ๊ฒฝ์ฐ HashCode
)๊ฐ ๋ ์ง์คํฐ์ ๋ค์ด๊ฐ ์ ์์ผ๋ฉด JIT๊ฐ ๋ ๋์ ์ฝ๋๋ฅผ ์์ฑํฉ๋๊น? int
์ ๋๋ง ๋ฉ๋๋ค.
๋ํ ์ต๊ทผ ๊ตฌ์กฐ์ฒด ์ฃผ๋ณ์์ ์์ฑ๋ ์ฝ๋๋ฅผ ๊ฐ์ ํ๊ธฐ ์ํด coreclr์์ ๋ง์ pull ์์ฒญ์ ๋ณด๊ณ ์์ผ๋ฉฐ 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);
.Value
ํธ์ถ์ ํ ํ์๊ฐ ์๋๋ก int
๋ก์ ๋ณํ์ ์ํ ์์์ ์ฐ์ฐ์๋ง ์์ผ๋ฉด ๋ฉ๋๋ค.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๊ฐ ๋ ์งง๊ณ ์ ๋ ฅํ๊ธฐ ์ฝ์ต๋๋ค. (Mix๋ ๋ ๋ค๋ฅธ ๋์์ด์ง๋ง ์ ๋ ฅํ๊ธฐ๊ฐ ์ฝ๊ฐ ์ด๋ ต์ต๋๋ค.)
Combine์ ํด์ฑ ์ปค๋ฎค๋ํฐ afaik์์ ์ฌ์ฉ๋๋ ์ค์ ์ด๋ฆ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ์ ๋น์ ์๊ฒ ๊ทธ๊ฒ์ด ๋ฌด์์ ํ๊ณ ์๋์ง์ ๋ํ ๋ช ํํ ์์ด๋์ด๋ฅผ ์ ๊ณตํฉ๋๋ค.
@jamesqo ๋ง์ ํด์ฑ ํจ์๊ฐ ์์ผ๋ฉฐ
๋ค์๊ณผ ๊ฐ์ ํ์ฅ ๊ฐ๋ฅํ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ์ฌ ์ด ๋์์ธ์์ ์์ผ๋ก ์๊ฐํ ์ ์์ต๋๋ค.
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 ๊ฐ๋ฐ์์๊ฒ ์์ฒญํด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋๋จธ์ง๋ ๋จ์ผ ๋ช ๋ น์ ๋ญ๋นํ์ง ์๊ณ ์ํ๋ ๋งํผ ๋ค์ํ Combiner๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค. ๊ทธ๋ ๊ธด ํ์ง๋ง ์ด ๋ฐฉ๋ฒ์ ๊ฒฐํฉ๊ธฐ๋ณด๋ค ์ค์ ํด์ ํจ์์ ๋ ์ ์ฉํ ์ ์์ต๋๋ค. cc @CarolEidt @AndyAyersMS
ํธ์ง: ์ฌ๊ธฐ์์ ๋จ์ผ ํด์ฑ ๊ฐ๋ ์ฐ์ฐ ์๋์์ ์ํธํ ๋ฐ ๋น์ํธํ ํด์ ๊ธฐ๋ฅ์ ๊ฒฐํฉํ๋ ์ผ๋ฐ์ ์ธ ๋ฉ์ปค๋์ฆ์ ๋ํด ํฌ๊ฒ ์๊ฐํฉ๋๋ค.
@jamesqo
๋น๋ ํจํด์ ๋ฐ๋ฅด๋ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๊ตฌ์กฐ์ฒด์ผ ํ์๋ ์์ต๋๋ค.
์ ์. ๊ทธ๋ฐ ๊ฒฝ์ฐ์๋ ๊ทธ ํจํด์ด ์ข์ต๋๋ค. ๋๋ ์ผ๋ฐ์ ์ผ๋ก ์์
์ ๋ถ์์ฉ์ด ์๋ ๊ฒฝ์ฐ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ ํจํด์ ์ข์ํ์ง ์์ต๋๋ค. API๊ฐ ๋ณ๊ฒฝํ ์ ์๋ WithXxx
ํจํด์ ๋ฐ๋ฅด๋ ๊ฒฝ์ฐ ํนํ ๋์ฉ๋๋ค. ํ์ง๋ง ์ด ๊ฒฝ์ฐ ํจํด์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ณ๊ฒฝํ ์ ์๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ด๋ฏ๋ก ํจํด์ด ์ ๋๋ก ์๋ํฉ๋๋ค.
๋๋ ์ฐ๋ฆฌ๊ฐ ๋น์ ๊ณผ ๋์ ์์ด๋์ด๋ฅผ ์ฝ๊ฐ ๊ฒฐํฉํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๐, ๊ทธ๋ผ ์ด๋จ๊น์?
``` C#
๊ณต๊ฐ ๊ตฌ์กฐ์ฒด ํด์ ์ฝ๋
{
๊ณต๊ฐ ์ ์ HashCode ๋ง๋ค๊ธฐ
[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 = ์๋ก์ด HashCode()
.Combine(IsMainPage ? 1:0)
.Combine(ViewName, StringComparer.Ordinal)
.Combine(์ปจํธ๋กค๋ฌ ์ด๋ฆ, StringComparer.Ordinal)
.Combine(์์ญ ์ด๋ฆ, StringComparer.Ordinal);
if (ViewLocationExpanderValues โโ!= null)
{
foreach(ViewLocationExpanderValues์ var ํญ๋ชฉ)
{
hashCode = hashCode.Combine(item.Key, StringComparer.Ordinal);
hashCode = hashCode.Combine(ํญ๋ชฉ.๊ฐ, StringComparer.Ordinal);
}
}
ํด์ ์ฝ๋.๊ฐ์ ๋ฐํํฉ๋๋ค.
```
@terrajobst ์๊ฐ:
Create<T>
ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ์ ๊ฑฐํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด HashCode.Create(_val)
๋๋ new HashCode().Combine(_val)
๊ฐ์ 2๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ๋ํ Create
/ Combine
๋ํด ๋ค๋ฅธ ์ด๋ฆ์ ์ฌ์ฉํ๋ฉด ์ฒซ ๋ฒ์งธ ํ๋๋ฅผ ์๋ก ์ถ๊ฐํ๋ฉด 2์ค์ ๋ณ๊ฒฝํด์ผ ํ๋ฏ๋ก diff ์นํ์ ์ด์ง ์์ต๋๋ค.HashCode
๋ ๋ฌธ์์ด๊ณผ ๊ด๋ จ์ด ์์ต๋๋ค. ๋์ ๋ฌธ์์ด์ GetHashCode(StringComparison)
API๋ฅผ ์ถ๊ฐํด์ผ ํ ๊น์? (๋ํ ์ด๋ค ๋ชจ๋๋ string.GetHashCode
์ ๊ธฐ๋ณธ ๋์์ธ ์์ ๋น๊ต์
๋๋ค.)Value
์ด๋ฏธ๋ก ๋ณํ ์์ ์ ์ฐ์ฐ์๊ฐ์๋ ๊ฒฝ์ฐ, int
? ๋ค์ ๋งํ์ง๋ง, ์ด๊ฒ์ ๋ค๋ฅธ ์ฌ๋๋ค์ด ๋ค๋ฅธ ๊ฒ์ ์์ฑํ๊ฒ ํ ๊ฒ์
๋๋ค.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#์ ์์์ ๋ณํ ์ฐ์ฐ์๋ฅผ ํธ์ถํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋๋ ์ธ์ด ์ค ํ๋์ ๋๋ค.
๋ํ, ์ผ์ ํ๋ ๋ฐฉ๋ฒ์ด ํ ๊ฐ์ง๋ง ์๋ ๊ฒ์ด ๊ทธ๋ ๊ฒ ์ค์ํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ์ ์๊ฐ์๋ API๋ฅผ ํธ๋ฆฌํ๊ฒ ๋ง๋๋ ๊ฒ์ด ๋ ์ค์ํฉ๋๋ค. ๋ ๊ทธ๋ฅ ๋ช ๊ฐ์ง ๊ฐ์ ํด์ ์ฝ๋๋ฅผ ๊ฒฐํฉํ๋ ค๋ ๊ฒฝ์ฐ์, ๋๋ ์๊ฐ HashCode.CombineHashCodes(value1, value2, value3)
๋ณด๋ค ์ดํดํ๊ธฐ, ๊ฐ๋จํ ์งง๊ณ ์ฝ๊ฒ new HashCode().Combine(value1).Combine(value2).Combine(value3)
.
์ธ์คํด์ค ๋ฉ์๋ API๋ ์ฌ์ ํ ๋ณต์กํ ๊ฒฝ์ฐ์ ์ ์ฉํ์ง๋ง ๋ ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ์๋ ๋ ๊ฐ๋จํ ์ ์ ๋ฉ์๋ API๊ฐ ์์ด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
@svick , ํฉ๋ฒ์ ์ธ ์ฐ์ฐ์๋ฅผ ์ง์ํ์ง ์๋ ๋ค๋ฅธ ์ธ์ด์ ๋ํ ๊ทํ์ ์์ . ์๋ณดํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด Value
๋ฅผ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
์ผ์ ํ๋ ๋ฐฉ๋ฒ์ด ํ ๊ฐ์ง๋ง ์๋ ๊ฒ์ด ๊ทธ๋ ๊ฒ ์ค์ํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
๊ทธ๊ฒ์ ์ค์ํ๋ค. ๋๊ตฐ๊ฐ๊ฐ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์ํํ๊ณ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ์ํํ๋ ์ฌ๋์ ์ฝ๋๋ฅผ ์ฝ์ผ๋ฉด ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก Google์ ๊ฒ์ํด์ผ ํฉ๋๋ค.
๋ช ๊ฐ์ง ๊ฐ์ ํด์ ์ฝ๋๋ฅผ ๊ฒฐํฉํ๋ ค๋ ๊ฒฝ์ฐ HashCode.CombineHashCodes(value1, value2, value3)๊ฐ new HashCode().Combine(value1).Combine(value2).Combine( ๊ฐ์น3).
- ์ ์ ๋ฉ์๋์ ๋ฌธ์ ๋
params int[]
์ค๋ฒ๋ก๋๊ฐ ์๊ธฐ ๋๋ฌธ์ ๊ฐ๊ฐ ๋ค๋ฅธ arity์ ๋ํด ์ค๋ฒ๋ก๋๋ฅผ ์ถ๊ฐํด์ผ ํ๋ฏ๋ก- ๋ ๋ฒ์งธ ํํ๋ ํ๋ ๋ฒ ๋ณด๋ฉด ์ดํดํ๊ธฐ ์ฌ์ธ ๊ฒ์ ๋๋ค. ์ฌ์ค, ์์ง์ผ๋ก ์ฐ๊ฒฐํ๋ ๊ฒ์ด ๋ ์ฝ๊ธฐ ๋๋ฌธ์ ๋ ์ฝ๊ธฐ ์ฝ๋ค๊ณ ์ฃผ์ฅํ ์ ์์ต๋๋ค(๋ฐ๋ผ์ ํ๋๊ฐ ์ถ๊ฐ/์ ๊ฑฐ๋ ๋ diff๋ฅผ ์ต์ํํจ).
public override int GetHashCode()
{
return new HashCode()
.Combine(_field1)
.Combine(_field2)
.Combine(_field3)
.Combine(_field4);
}
[@svick] ์ผ์ ํ๋ ๋ฐฉ๋ฒ์ด ํ ๊ฐ์ง๋ง ์๋ ๊ฒ์ด ๊ทธ๋ ๊ฒ ์ค์ํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
ํผ๋์ ํผํ๊ธฐ ๋๋ฌธ์ ๊ฐ์ ์ผ์ ํ ์ ์๋ ๋ฐฉ๋ฒ์ ์๋ฅผ ์ต์ํํ๋ ๊ฒ์ด ์ค์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋์์ ์ฐ๋ฆฌ์ ๋ชฉํ๋ ๊ฒ์ ๊ฐ๋ฅ์ฑ, ํธ์์ฑ, ์ฑ๋ฅ ๋๋ ๊ฐ๋ ์ฑ๊ณผ ๊ฐ์ ๋ค๋ฅธ ๋ชฉํ๋ฅผ ์คํํ๋ ๋ฐ ๋์์ด๋๋ค๋ฉด 100% ์ค๋ณต๋์ง ์๋ ๊ฒ์ด ์๋๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ฐ๋ฆฌ์ ๋ชฉํ๋ API๋ณด๋ค๋ ๊ฐ๋ ์ ์ต์ํํ๋ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค์ค ์ค๋ฒ๋ก๋๋ ๋ถ๋ฆฌ๋ ์ฉ์ด๋ฅผ ์ฌ์ฉํ๋ ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค ๋ฌธ์ ๊ฐ ์ ์ต๋๋ค.
๋ด๊ฐ ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ ์ด์ ๋ ์ด๊ธฐ ํด์ ์ฝ๋๋ฅผ ์ป๋ ๋ฐฉ๋ฒ์ ๋ช
ํํ ํ๊ธฐ ์ํด์์
๋๋ค. Combine
๋ค์ ์ค๋ ๋น ๊ตฌ์กฐ์ฒด๋ฅผ ๋ง๋๋ ๊ฒ์ ๋งค์ฐ ์ง๊ด์ ์ด์ง ์์ต๋๋ค. ๋
ผ๋ฆฌ์ ์ธ ๊ฒ์ .ctor๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด์ง๋ง boxing์ ํผํ๊ธฐ ์ํด์๋ .ctor๋ก๋ ํ ์ ์๋ ์ผ๋ฐ์ ์ด์ด์ผ ํฉ๋๋ค. ์ ๋ค๋ฆญ ํฉํ ๋ฆฌ ๋ฉ์๋๊ฐ ์ฐจ์ ์ฑ
์
๋๋ค.
์ข์ ๋ถ์์ฉ์ ํ๋ ์์ํฌ์์ ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ๊ฐ ์ด๋ป๊ฒ ๋ณด์ด๋์ง ๋งค์ฐ ์ ์ฌํ๊ฒ ๋ณด์ธ๋ค๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ API ๋์์ธ์์ ์ฐ๋ฆฌ๋ ๊ฑฐ์ ๋ชจ๋ ๊ฒ๋ณด๋ค ์ผ๊ด์ฑ์ ๊ฐ๋ ฅํ ์ ํธํฉ๋๋ค.
[@svick] ์ ์ ์์ ํด์ ์ฝ๋๋ฅผ ๊ฒฐํฉํ๊ณ ์ถ๋ค๋ฉด HashCode.CombineHashCodes(value1, value2, value3)๊ฐ new HashCode().Combine(value1).Combine(value2)๋ณด๋ค ๋ ๊ฐ๋จํ๊ณ ์งง๊ณ ์ดํดํ๊ธฐ ์ฝ๋ค๊ณ ์๊ฐํฉ๋๋ค. ).๊ฒฐํฉ(๊ฐ3).
@jamesqo์ ๋์ํฉ๋๋ค. ์ต์ํ์ ์ฑ๋ฅ ํจ๋ํฐ๋ก ์์์ ์์ ์ธ์๋ก ํ์ฅ๋๋ ๋น๋ ํจํด์ ๋ํด ์ ๊ฐ ์ข์ํ๋ ์ (์๋ ๊ฒฝ์ฐ ์ธ๋ผ์ธ์ด ์ผ๋ง๋ ์ข์์ง์ ๋ฐ๋ผ ๋ค๋ฆ).
[@jamesqo] string/StringComparison์ ์๋ฝํ๋ ์ค๋ฒ๋ก๋๊ฐ ์ฌ๊ธฐ์ ์ํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. HashCode๋ ๋ฌธ์์ด๊ณผ ๊ด๋ จ์ด ์์ต๋๋ค.
๊ณต์ ํ ์ง์ ์ ๋๋ค. @Eilon ์ ์ฝ๋์์ ์ฐธ์กฐํ๊ธฐ ๋๋ฌธ์ ์ถ๊ฐํ์ต๋๋ค. ๊ฒฝํ์ ๋ฐ๋ฅด๋ฉด ๋ฌธ์์ด์ ๋งค์ฐ ์ผ๋ฐ์ ์ ๋๋ค. ๋ฐ๋ฉด์ ๋น๊ต๋ฅผ ์ง์ ํ๋ ๊ฒ์ด ํ์คํ์ง ์์ต๋๋ค. ์ผ๋จ์ ๋๋์.
[@jamesqo] ๊ธด ์ค๋ฒ๋ก๋๋ฅผ ์๋ก์ด ์ ํ์ผ๋ก ์ฎ๊ฒจ์ผ ํฉ๋๋ค.
HashCode
๋๋น๋ 32๋นํธ์ ๋๋ค. ๊ธธ์ง ์์ต๋๋ค.
๊ทธ๊ฑด ์ข์ ์ง์ ์ด์ผ. long
๋ฒ์ ์ด ํ์ํฉ๋๊น? ์์์ ์ธ๊ธํ ๋ด์ฉ์ด๋ผ ๋ณ ์๊ฐ ์์ด ๊ทธ๋ฅ ๋์์ต๋๋ค.
์ด์ .NET GetHashCode()
์ ๋ํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ 32๋นํธ๋ง ๋จ๊ฒจ์ผ ํฉ๋๋ค. ๊ทธ๋ฐ ๋งฅ๋ฝ์์ uint
๋ฒ์ ์ ์ถ๊ฐํด์ผ ํ๋์ง๋ ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ํด๋น ์์ญ ์ธ๋ถ์์ ํด์ฑ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ System.Security.Cryptography
์ ์๋ ๋ณด๋ค ์ผ๋ฐ์ ์ธ ๋ชฉ์ ์ ํด์ฑ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ๋๋ค์๊ฒ ์๋ ค์ฃผ๋ ๊ฒ์ด ์ข์ต๋๋ค.
```C#
๊ณต๊ฐ ๊ตฌ์กฐ์ฒด ํด์ ์ฝ๋
{
๊ณต๊ฐ ์ ์ HashCode ๋ง๋ค๊ธฐ
[Pure] public HashCode Combine(int hashCode);
[Pure] public HashCode Combine<T>(T obj);
public int Value { get; }
public static implicit operator int(HashCode hashCode);
}
```
์ด์ .NET GetHashCode()๊ฐ ๋ฐ๋ก 32๋นํธ์ด๊ธฐ ๋๋ฌธ์ 32๋นํธ๋ง ๋จ๊ฒจ์ผ ํ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ฐ ์ ์์ 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์ ๋์ํฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ Object.GetHashCode ์ฌ์ ์์์ ํด์๋ฅผ ๋ฐํํ ๋ชฉ์ ์ผ๋ก ํด์๋ฅผ ๊ณ์ฐํ๋ API์ ๊ดํ ๊ฒ์ด์ด์ผ ํฉ๋๋ค. ์ฐ๋ฆฌ๋ ๋ํ ๋ ํ๋์ ์ธ ํด์ฑ์ ์ํ ๋ณ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ์ง ์ ์์ง๋ง Object.GetHashCode ๋ฐ ๊ธฐ์กด์ ๋ชจ๋ ํด์ฑ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ก ์ํํ ์์ ์ ๊ฒฐ์ ํ๋ ๊ฒ์ด ํฌํจ๋์ด์ผ ํ๋ฏ๋ก ๋ณ๋์ ๋ ผ์๊ฐ ํ์ํ๋ค๊ณ ๋งํ๊ณ ์ถ์ต๋๋ค.
128๋นํธ์์ ํด์ ๊ฒฐํฉ์ ์ํํ ๋ค์ GetHahsCode์์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ ์ ์๋๋ก int๋ก ๋ณํํ๋ ๊ฒ์ด ์ฌ์ ํ ์ ์ตํ๋ค๊ณ ์๊ฐํ์ง ์๋ ํ.
@KrzysztofCwalina ๋๋ ๊ทธ๊ฒ์ด ๋ ๊ฐ์ง ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ์์ด๋ผ๋ ๋ฐ ๋์ํฉ๋๋ค. ํ๋๋ 2000๋ ์ ๋ฐ์ํ ๋ฌธ์ ๋ฅผ ์์ ํ๋ ๊ฒ์ ๋๋ค. ๋ค๋ฅธ ํ๋๋ ์ผ๋ฐ์ ์ธ ํด์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ์ด๊ฒ์ด ์ ์์ ๋ํ ํด๊ฒฐ์ฑ ์ด๋ผ๋ ๋ฐ ๋์ํ๋ค๋ฉด ํ ๋ก ์ ๋๋๋ค. ๊ทธ๋ฌ๋ "๋ฏธ๋" ์ด์ ํ์ ๋ํ ์ค๊ณ ํ ๋ก ์ ๊ฒฝ์ฐ, ๋๋ถ๋ถ ์ฌ๊ธฐ์ ์ฐ๋ฆฌ๊ฐ ํ ์ผ์ด ํฅํ ํ ๋ก ์ ์ํฅ์ ๋ฏธ์น๊ธฐ ๋๋ฌธ์ ๋ถ์กฑํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ฌ๊ธฐ์ ์ค์๋ฅผ ํ๋ฉด ์ํฅ์ ๋ฏธ์นฉ๋๋ค.
@redknightlois , ์ ๋ ๋ค์์ ์ ์ํฉ๋๋ค: ๋ฏธ๋์ ๋ํด ๊ฑฑ์ ํ ํ์๊ฐ ์๋ ๊ฒ์ฒ๋ผ API๋ฅผ ์ค๊ณํฉ์๋ค. ๊ทธ๋ฐ ๋ค์ ๋ฏธ๋ API์ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ๊ฒ์ผ๋ก ์๊ฐ๋๋ ๋์์ธ ์ ํ์ ๋ํด ๋ ผ์ํด ๋ณด๊ฒ ์ต๋๋ค. ๋ํ ์ฐ๋ฆฌ๊ฐ ํ ์ ์๋ ์ผ์ c2000 API๋ฅผ corfx์ ์ถ๊ฐํ๋ ๊ฒ๊ณผ ๋์์ corfxlab์์ ๋ฏธ๋ API๋ฅผ ์คํํ๋ ๊ฒ์ ๋๋ค.
@redknightlois
์ฌ๊ธฐ์ ์ค์๋ฅผ ํ๋ฉด ์ํฅ์ ๋ฏธ์นฉ๋๋ค.
์์ผ๋ก ๋ ๊ณ ๊ธ ์๋๋ฆฌ์ค๋ฅผ ์ง์ํ๋ ค๋ ๊ฒฝ์ฐ HashCode
์์ ๋ณ๋์ ์ ํ์ผ๋ก ์ง์ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ฌ๊ธฐ์์์ ๊ฒฐ์ ์ ์ด๋ฌํ ๊ฒฝ์ฐ์ ์ค์ ๋ก ์ํฅ์ ๋ฏธ์น์ง ์์์ผ ํฉ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ๋ง๋ค์์ต๋๋ค.
@redknightlois :+1:. Btw, ๋น์ ์ ๋ด๊ฐ ๋ด ์๊ฒฌ์ ํธ์งํ๊ธฐ ์ ์ ์๋ตํ์ง๋ง ์ค์ ๋ก ํด์๊ฐ ๋ชจ๋ ์ ํ(int, long, decimal ๋ฑ)๊ณผ ํจ๊ป ์๋ํ๋๋ก ํ๊ณ ํต์ฌ ํด์ฑ ๋ ผ๋ฆฌ๋ฅผ ๊ตฌ์กฐ์ฒด๋ก ์บก์ํํ๋ ์์ด๋์ด(์)๋ฅผ ์๋ํ์ต๋๋ค. https://github.com/jamesqo/HashApi (์ํ ์ฌ์ฉ๋ฒ์ ์ฌ๊ธฐ ). ๊ทธ๋ฌ๋ ๋ ๊ฐ์ ์ ๋ค๋ฆญ ์ ํ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ฌด ๋ณต์กํ๊ณ API๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ ๋ ์ปดํ์ผ๋ฌ ์ ํ ์ ์ถ๊ฐ ์๋ํ์ง ์๊ฒ ๋์์ต๋๋ค. ์, ์ง๊ธ์ ๋ณ๋์ ๋ฌธ์ ๋ก ๊ณ ๊ธ ํด์ฑ์ ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
@terrajobst API๊ฐ ๊ฑฐ์ ์ค๋น๋ ๊ฒ ๊ฐ์ง๋ง 1~2๊ฐ์ง ๋ ๋ณ๊ฒฝํ๊ณ ์ถ์ ์ฌํญ์ด ์์ต๋๋ค.
HashCode.Create(x)
๋ new HashCode().Combine(x)
์ ๋์ผํ ํจ๊ณผ๋ฅผ Create
์ Combine
๋ฐ๊พธ์ง ์๊ฒ ์ต๋๊น? ์ฒซ ๋ฒ์งธ ํ๋์ ํ๋๋ฅผ ์
๋ ฅํ๊ณ ๋ ๋ฒ์งธ ํ๋์ ๋ค๋ฅธ ๊ฒ์ ์
๋ ฅํด์ผ ํ๋ ๊ฒ์ ๋ค์ ์ฑ๊ฐ์ ์ผ์ธ ๊ฒ ๊ฐ์ต๋๋ค.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
{
๊ณต๊ฐ ๊ตฌ์กฐ์ฒด ํด์ ์ฝ๋: IEquatable
{
๊ณต๊ฐ ์ ์ HashCode ๊ฒฐํฉ(int ํด์);
๊ณต๊ฐ ์ ์ HashCode ๊ฒฐํฉ
public static HashCode Combine(๋ฌธ์์ด ํ
์คํธ, StringComparison ๋น๊ต);
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();
}
}
// ์ฉ๋ฒ:
๊ณต๊ฐ ์ฌ์ ์ int GetHashCode()
{
๋ฐํ HashCode.Combine(_field1)
.๊ฒฐํฉ(_field2)
.๊ฒฐํฉ(_field3)
.๊ฒฐํฉ(_field4);
}
```
๋ฐฐ์ก! :-)
@terrajobst _ ์ ์๋ง--_ 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 ์ด ์ด๊ฒ์ด ๋ด์ฅ๋ ๋ฐฉ๋ฒ์ด์ด์ผ ํ๋ค๊ณ ์ ๋์ ์ผ๋ก ์๊ฐํ๋ค๋ฉด ๋๋ ์ด ์ ์์ ์ฐจ๋จํ์ง ์์ ๊ฒ์ ๋๋ค.
( ํธ์ง : ์ค๋๋ ๋ด๊ฐ ์์ง ๋ชปํ๋ Collection.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 ์ข์, ๊ทธ๋ผ ์ถ๊ฐํ์ @redknightlois๊ฐ ์ ์ํ ๊ฒ์ฒ๋ผ ์์ผ๋ก ํด์ฑ ๊ด๋ จ ์ ํ์ ๋ ์ถ๊ฐํ๋ค๋ฉด Collections์์ ์๋ชป๋ ์ด๋ฆ์ด ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๋๋ ๊ทธ๊ฒ์ ์ข์ํด. ๐
๋๋ ํด์ฑ์ด ๊ฐ๋ ์ ์ผ๋ก ์ปฌ๋ ์ ์ ์ํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค. System.Runtime์ ์ด๋ป์ต๋๊น?
๋๋ ๋์ผํ๊ฑฐ๋ ์ฌ์ง์ด ์์คํ ์ ์ ์ํ๋ ค๊ณ ํ์ต๋๋ค. ์ซ์๋ ์๋๋๋ค.
@karelz , System.Runtime์ด ์๋ํ ์ ์์ต๋๋ค. @redknightlois ์์คํ ์ ์ด๋ฏธ ํด๋น ๋ค์์คํ์ด์ค๋ฅผ ๊ฐ์ ธ์์ ๊ฐ๋ฅ์ฑ์ด ์์ผ๋ฏ๋ก ํธ๋ฆฌํ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ด ์ ์ ํ์ง ์ฌ๋ถ๋ ์ ์ ์์ต๋๋ค(๋ค์ ๋งํ์ง๋ง ๋ ๋ง์ ํด์ฑ ์ ํ์ด ์ถ๊ฐ๋๋ ๊ฒฝ์ฐ).
๋ํดํ๊ณ ๋งค์ฐ ์ ๋ฌธ์ ์ธ ๊ฒฝ์ฐ๋ฅผ ์ํ ๊ฒ์ด๋ฏ๋ก System.Runtime
์ ๋ฃ์ผ๋ฉด ์ ๋ฉ๋๋ค. ๋๋ @KrzysztofCwalina ์ ์ด์ผ๊ธฐํ๊ณ ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ด ๋ ์ค ํ๋๋ผ๊ณ ์๊ฐํฉ๋๋ค.
System
System.Collections.*
์ฐ๋ฆฌ๋ ๋ ๋ค System
์ชฝ์ผ๋ก ๊ธฐ์ธ๊ณ ์์ต๋๋ค.
์ฐ๋ฆฌ์๊ฒ ํ์ํ ๊ฒ์ด System
ํ๋ ์ด์ ๋ผ๋ฉด ์ ๋นํ๋ฅผ ์๋ํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ object.GetHashCode()
๊ตฌํ์ ๋๊ธฐ ์ํด HashCode
๋ฅผ ๋ง๋ค์์ต๋๋ค. ๋ ๋ค ๋ค์์คํ์ด์ค๋ฅผ ๊ณต์ ํ๋ ๊ฒ์ด ์ ์ ํด ๋ณด์
๋๋ค.
@terrajobst ๊ทธ๋ฌ๋ฉด System
๊ฐ ๋ค์์คํ์ด์ค์ฌ์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ํ์ :shipit:
์ค๋ช ์์ API ์ฌ์์ ์ ๋ฐ์ดํธํ์ต๋๋ค.
[@redknightlois] ์ฐ๋ฆฌ์๊ฒ ํ์ํ ๊ฒ์ด
System
ํ๋ ์ด์ ๋ผ๋ฉด ์ ๋นํ๋ฅผ ์๋ํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋object.GetHashCode()
๊ตฌํ์ ๋๊ธฐ ์ํดHashCode
๋ฅผ ๋ง๋ค์์ต๋๋ค. ๋ ๋ค ๋ค์์คํ์ด์ค๋ฅผ ๊ณต์ ํ๋ ๊ฒ์ด ์ ์ ํด ๋ณด์ ๋๋ค.
์ ์ @KrzysztofCwalina ๋ ์ฌ์ฉํ ๊ทผ๊ฑฐ์์ต๋๋ค. ํ๋งค ๋!
@jamesqo
๋๋ ๋น์ ์ด ๊ตฌํ๊ณผ ํจ๊ป PR๋ ์ ๊ณตํ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํฉ๋๊น?
@terrajobst ๋ค, ๋ฌผ๋ก ์ ๋๋ค. ์๊ฐ์ ๋ด์ด ๊ฒํ ํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
๋ค, ๋ฌผ๋ก ์ ๋๋ค.
๋ฌ์ฝคํ. ๊ทธ๋ฐ ๊ฒฝ์ฐ์๋ ๊ทํ์๊ฒ ๋งก๊ธฐ๊ฒ ์ต๋๋ค. @karelz๋ ์ ์ง๋ด์์ฃ ?
์๊ฐ์ ๋ด์ด ๊ฒํ ํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
์๊ฐ์ ๋ด์ด API ํํ์ ๋ํด ์์ ํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์๋ค ๊ฐ๋ค ํ๋ ๊ฒ์ ๊ณ ํต์ค๋ฌ์ด ๊ณผ์ ์ผ ์ ์์ต๋๋ค. ์ํดํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ ๋ ASP.NET Core ๊ตฌํ์ ์ญ์ ํ๊ณ ๋์ ์ด๊ฒ์ ์ฌ์ฉํ๊ธฐ๋ฅผ ๊ณ ๋ํ๊ณ ์์ต๋๋ค ๐
public static HashCode Combine(๋ฌธ์์ด ํ ์คํธ, StringComparison ๋น๊ต);
public HashCode Combine(๋ฌธ์์ด ํ ์คํธ, StringComparison ๋น๊ต);
NIT ๋ค์ ๋ฉ์๋ String
์ด ๊ฑธ๋ฆด StringComparison
(์ Equals
, Compare
, StartsWith
, EndsWith
๋ฑ .)๋ฅผ ์ฌ์ฉํ์ฌ comparisonType
๋งค๊ฐ ๋ณ์์ ์ด๋ฆ,ํ์ง๋ก comparison
. ์ฌ๊ธฐ์์๋ ๋งค๊ฐ๋ณ์์ ์ด๋ฆ์ comparisonType
๋ก ์ง์ ํด์ผ ์ผ๊ด์ฑ์ด ์์ต๋๊น?
@justinvp , ๊ทธ๊ฒ์ String ๋ฉ์๋์ ๋ช
๋ช
๊ฒฐํจ์ฒ๋ผ ๋ณด์
๋๋ค. Type
์(๋) ์ค๋ณต๋ฉ๋๋ค. ์ด์ API์ "์ ๋ก๋ฅผ ๋ฐ๋ฅด๊ธฐ" ์ํด ์ API์ ๋งค๊ฐ๋ณ์ ์ด๋ฆ์ ๋ ์ฅํฉํ๊ฒ ๋ง๋ค์ด์ผ ํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
๋ ๋ค๋ฅธ ๋ฐ์ดํฐ ํฌ์ธํธ๋ก xUnit ์ comparisonType
๋ ์ฌ์ฉํ๊ธฐ๋ก ํ์ต๋๋ค.
@justinvp ๋น์ ์ ๋๋ฅผ ์ค๋ํ์ต๋๋ค. ์ด์ ์ง๊ด์ ์ผ๋ก ์๊ฐํด๋ณด๋ฉด "๋์๋ฌธ์ ๊ตฌ๋ถํ์ง ์์" ๋๋ "๋ฌธํ ์ข ์์ "์ ๋น๊ต์ '์ ํ'์ ๋๋ค. ์ด๋ฆ์ ๋ฐ๊พธ๊ฒ ์ต๋๋ค.
๋๋ ์ด๊ฒ์ ๋ชจ์์ ๋ฌธ์ ๊ฐ ์์ง๋ง ๊ฐ๋ฅํ ๋์์ธ StringComparison์ ๊ดํด์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋ค์์ ํฌํจํ์ง ๋ง์ญ์์ค.
``` C#
public static HashCode Combine(๋ฌธ์์ด ํ
์คํธ, StringComparison ๋น๊ต);
public HashCode Combine(๋ฌธ์์ด ํ
์คํธ, StringComparison ๋น๊ต);
Instead, add a method:
``` C#
public class StringComparer
{
public static StringComparer FromComparison(StringComparison comparison);
...
}
๊ทธ๋ฐ ๋ค์ ์์ฑํ๋ ๋์ :
``` C#
๊ณต๊ฐ ์ฌ์ ์ int GetHashCode()
{
๋ฐํ HashCode.Combine(_field1)
.๊ฒฐํฉ(_field2)
.๊ฒฐํฉ(_field3)
.Combine(_field4, _๋น๊ต);
}
you write:
``` C#
public override int GetHashCode()
{
return HashCode.Combine(_field1)
.Combine(_field2)
.Combine(_field3)
.Combine(StringComparer.FromComparison(_comparison).GetHashCode(_field4));
}
์, ์กฐ๊ธ ๋ ๊ธธ์ง๋ง HashCode(๋ฐฉ๊ธ ์์คํ ์ผ๋ก ์น๊ฒฉํ)์ ๋ํ ๋ ๊ฐ์ง ํน์ ๋ฉ์๋ ์์ด ๋์ผํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ๊ด๋ จ ์๋ ๋ค๋ฅธ ์ํฉ์์ ์ฌ์ฉํ ์ ์๋ ์ ์ ๋์ฐ๋ฏธ ๋ฉ์๋๋ฅผ ์ป์ต๋๋ค. ๋ํ ์ด๋ฏธ 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 ๋น์ ์ด ์ธ๊ธํ ํจํด์ ASP.NET Core ์์ฒด์์ ์ฌ์ฉ๋ฉ๋๋ค. ์ธ๋ถ ๊ฐ๋ฐ์๊ฐ ์ผ๋ง๋ ์ฌ์ฉํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๊น?
@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(๋ฐฉ๊ธ ์์คํ ์ผ๋ก ์น๊ฒฉํ)์ ๋ํ ๋ ๊ฐ์ง ํน์ ๋ฉ์๋ ์์ด ๋์ผํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ๊ด๋ จ ์๋ ๋ค๋ฅธ ์ํฉ์์ ์ฌ์ฉํ ์ ์๋ ์ ์ ๋์ฐ๋ฏธ ๋ฉ์๋๋ฅผ ์ป์ต๋๋ค. ๋ํ ์ด๋ฏธ StringComparer๊ฐ ์๋ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ ์ ์ฌํ๊ฒ ์ ์งํฉ๋๋ค(๋น๊ต์ ์ค๋ฒ๋ก๋์ ๋ํด ์ด์ผ๊ธฐํ์ง ์๊ธฐ ๋๋ฌธ์).
๊ธ์์, ๊ทธ๊ฒ์ ๋จ์ง ์กฐ๊ธ ๋ ๊ธด ๊ฒ์ด ์๋๋ผ ์ ๋ง ๋ ๊ธธ์ด์ง๊ณ ๋ฐ๊ฒฌ ๊ฐ๋ฅ์ฑ์ด ์ ํ ์๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
์ด ๋ฐฉ๋ฒ์ ์ถ๊ฐํ๋ ๊ฒ์ ๋ํ ์ ํญ์ ๋ฌด์์ ๋๊น? ์ ์ฉํ๊ณ ์ ํํ๊ฒ ๊ตฌํ๋ ์ ์๊ณ ํ๋ ์ผ์ ๋ชจํธํจ์ด ์๋ค๋ฉด ์ถ๊ฐํ์ง ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
์ ์ ๋์ฐ๋ฏธ/๋ณํ ๋ฐฉ๋ฒ์ ์ถ๊ฐ๋ก ์ฌ์ฉํ๋ ๊ฒ์ ๊ด์ฐฎ์ต๋๋ค. ์ฌ์ฉํ ์ง๋ ๋ชจ๋ฅด๊ฒ ์ง๋ง ํธ๋ฆฌํ ๋ฐฉ๋ฒ์ ํฌ์ํ๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
ํธ์ ๋ฐฉ๋ฒ์ ํฌ์ํ๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
๋์๊ฒ ํธ๋ฆฌํ ๋ฐฉ๋ฒ์ด ๋ช ํํ์ง ์๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์ ์ ๋ง ํ์ํฉ๋๋ค. 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 ๋ด๋ถ์์ ๋ถ๊ธฐํ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก ๋ ๋น ๋ฆ
๋๋ค. ์ถ๊ฐ ์ฝ๋๊ฐ ๊ทธ ํ ๊ฐ์ง ๊ฒฝ์ฐ์ ๋ํด ํน์ ์ค๋ฒ๋ก๋๋ฅผ ์ถ๊ฐํ ๊ฐ์น๊ฐ ์๋ ๋ถํธํจ์ด ์์ต๋๊น? StringComparer์ ๋ํ ์ค๋ฒ๋ก๋๊ฐ ์๋ ์ด์ ๋ ๋ฌด์์
๋๊น? EqualityComparer์ ๊ณผ๋ถํ๊ฐ ๊ฑธ๋ฆฌ์ง ์๋ ์ด์ ๋ ๋ฌด์์
๋๊น? Func<T, int>
๋ฅผ ์ฌ์ฉํ๋ ์ค๋ฒ๋ก๋๊ฐ ์๋ ์ด์ ๋ ๋ฌด์์
๋๊น? ์ด๋ ์์ ์์ ๋น์ ์ ์ ์ ๊ทธ๋ฆฌ๊ณ "์ด ๊ณผ๋ถํ๊ฐ ์ ๊ณตํ๋ ๊ฐ์น๋ ๊ทธ๋งํ ๊ฐ์น๊ฐ ์๋ค"๊ณ ๋งํฉ๋๋ค. ์๋ํ๋ฉด ์ฐ๋ฆฌ๊ฐ ์ถ๊ฐํ๋ ๋ชจ๋ ๊ฒ์ ์ ์ง ๋น์ฉ์ด๋ , ์ฝ๋ ํฌ๊ธฐ ๋น์ฉ์ด๋ , ๋ฌด์์ด๋ ๋น์ฉ์ด ๋ค๊ธฐ ๋๋ฌธ์
๋๋ค. , ๊ฐ๋ฐ์๊ฐ ์ด ์ผ์ด์ค๋ฅผ ์ ๋ง๋ก ํ์๋ก ํ๋ค๋ฉด, ๊ฐ๋ฐ์๊ฐ ๋ ์ ์ ์์ ํน์ ์ผ์ด์ค๋ก ์ฒ๋ฆฌํ ์ถ๊ฐ ์ฝ๋๊ฐ ๊ฑฐ์ ์์ต๋๋ค. ๊ทธ๋์ ๋๋ ์ ์ ๊ทธ์ ์ ์๋ ์ ์ ํ ์ฅ์๊ฐ ์ค๋ฒ๋ก๋ ์ดํ๊ฐ ์๋๋ผ ์ด๋ฌํ ์ค๋ฒ๋ก๋ ์ด์ ์ผ ๊ฒ์ด๋ผ๊ณ ์ ์ํ๊ณ ์์์ต๋๋ค(๊ทธ๋ฌ๋ ์ด์ ์๋ต์ ์์ ๋ถ๋ถ์์ ์ธ๊ธํ๋ฏ์ด "๋๋ ์ด ๋ชจ์์ผ๋ก ๊ด์ฐฎ์ต๋๋ค"ํ๊ณ ๋์์ ์ ์ํ๊ณ ์์์ต๋๋ค) .
๋ด๊ฐ ํ ๊ฒ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. https://github.com/search?p=2&q=user%3Aaspnet+hashcodecombiner&type=Code&utf8=%E2%9C%93
~100๊ฐ์ ์ผ์น ํญ๋ชฉ ์ค ์ฒ์ ๋ช ํ์ด์ง๋ถํฐ ๊ฑฐ์ ๋ชจ๋ ์ฌ์ฉ ์ฌ๋ก์๋ ๋ฌธ์์ด์ด ์์ผ๋ฉฐ ์ฌ๋ฌ ๊ฒฝ์ฐ์๋ ๋ค์ํ ์ข ๋ฅ์ ๋ฌธ์์ด ๋น๊ต๋ฅผ ์ฌ์ฉํฉ๋๋ค.
(๊ทธ๋ฆฌ๊ณ ์์ญ๋ช ์ ๋ค๋ฅธ ์ฌ๋๋ค.)
๋ฐ๋ผ์ ํ์คํ ASP.NET Core ์ฝ๋๋ฒ ์ด์ค ๋ด์์ ์ด๊ฒ์ ๋งค์ฐ ์ผ๋ฐ์ ์ธ ํจํด์ธ ๊ฒ ๊ฐ์ต๋๋ค. ๋ฌผ๋ก ๋ค๋ฅธ ์์คํ ๊ณผ ๋ํํ ์๋ ์์ต๋๋ค.
~100๊ฒฝ๊ธฐ ์ค
๋น์ ์ด ๋์ดํ 10๊ฐ ์ค ํ๋(๋๋จธ์ง ๊ฒ์์ ๋ณด์ง ์์์ต๋๋ค)๋ ๋ณ์์์ ๊ฐ์ ธ์ค๋ ๊ฒ์ด ์๋๋ผ ๋ฌธ์์ด ๋น๊ต๋ฅผ ๋ช ์์ ์ผ๋ก ์ง์ ํ๋ฏ๋ก ๋ค์๊ณผ ๊ฐ์ ์ฐจ์ด์ ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์๋ ๊ฒ์ด ์๋๋๋ค.
``` C#
.Combine(์ด๋ฆ, StringComparison.OrdinalIgnoreCase)
``` C#
.Combine(StringComparer.OrdinalIgnoreCase.GetHashCode(Name))
? ๋ด๊ฐ ๋ญ๊ฐ๋ฅผ ๋์น๊ณ ์์ง ์๋ ํ "์ ๋ง ๋ ์ด์"์ด ์๋๋ฉฐ ๋ ํจ์จ์ ์ ๋๋ค.
์ด์จ๋ , ๋ด๊ฐ ๋งํ๋ฏ์ด, ๋๋ ๋จ์ํ ์ฐ๋ฆฌ๊ฐ ์ด๋ฌํ ๊ณผ๋ถํ๊ฐ ํ์ํ์ง ์ฌ๋ถ๋ฅผ ์ ๋ง๋ก ๊ณ ๋ คํ ๊ฒ์ ์ ์ํ๋ ๊ฒ์ ๋๋ค. ๋๋ถ๋ถ์ ์ฌ๋๋ค์ด ๊ทธ๋ ๋ค๊ณ ๋ฏฟ๊ณ ์๊ณ ์ฐ๋ฆฌ ์์ ์ ASP.NET ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๊ณ ๋ คํ๊ณ ์์ง ์๋ค๋ฉด ๊ด์ฐฎ์ต๋๋ค.
๊ด๋ จํ์ฌ null ์ ๋ ฅ์ ๋ํด ๊ณํ ์ค์ธ ๋์์ ๋ฌด์์ ๋๊น? int==0์ ์ด๋ป์ต๋๊น? StringComparer.GetHashCode๊ฐ ์ผ๋ฐ์ ์ผ๋ก null ์ ๋ ฅ์ ๋ํด throwํ๋ค๊ณ ์๊ฐํ๋ฏ๋ก null์ ์ ๋ฌํ๋๋ก ํ์ฉํ๋ฉด ๋ฌธ์์ด ์ค๋ฒ๋ก๋์ ๋ํ ๋ ๋ง์ ์ด์ ์ ๋ณผ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ด๊ฒ์ด ์ค์ ๋ก ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ ํธ์ถ์๊ฐ ํน๋ณํ ๊ฒฝ์ฐ null. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ๋ํ null์ด ์ ๊ณต๋ ๋ ๋์์ด ๋ฌด์์ธ์ง์ ๋ํ ์ง๋ฌธ์ ์ ๊ธฐํฉ๋๋ค. ๋ค๋ฅธ ๊ฐ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ํด์ ์ฝ๋์ 0์ด ํผํฉ๋์ด ์์ต๋๊น? ๊ทธ๊ฒ์ nop ๋ฐ ํด์ ์ฝ๋๋ก ์ฒ๋ฆฌ๋ฉ๋๊น?
null์ ๋ํ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ 0์ ํผํฉํ๋ ๊ฒ์ ๋๋ค. ์ถ๊ฐ๋ ๋จ์ผ null ์์์ ๊ฒฝ์ฐ nop์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข์ง๋ง ๋๊ตฐ๊ฐ ์ํ์ค๋ก ๊ณต๊ธํ๋ ๊ฒฝ์ฐ 10๊ฐ์ null ํด์๋ฅผ 20๊ณผ ๋ค๋ฅด๊ฒ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ ๋ฆฌํฉ๋๋ค.
์ค์ ๋ก ๋ด ํฌํ๋ ๋ฌธ์์ด์ ์ธ์ํ๋ ์ค๋ฒ๋ก๋๊ฐ ์์ผ๋ฉด ๋งค์ฐ ๋์์ด ๋๋ ASP.NET Core์ ์ฝ๋๋ฒ ์ด์ค ๊ด์ ์์ ๋์จ ๊ฒ์ ๋๋ค. ์ค ๊ธธ์ด์ ๊ดํ ๊ฒ์ ๋ด ์ฃผ์ ๊ด์ฌ์ฌ๊ฐ ์๋๋ผ ๊ฒ์ ๊ฐ๋ฅ์ฑ์ ๊ดํ ๊ฒ์ด์์ต๋๋ค.
์์คํ ์์ ๋ฌธ์์ด ์ธ์ ์ค๋ฒ๋ก๋๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ฒฝ์ฐ ASP.NET Core์ ๋ด๋ถ ํ์ฅ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๊ณ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
์์คํ ์์ ๋ฌธ์์ด ์ธ์ ์ค๋ฒ๋ก๋๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ฒฝ์ฐ ASP.NET Core์ ๋ด๋ถ ํ์ฅ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๊ณ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
์ด๋ฌํ API๊ฐ ์ผ๋ฐ์ ์ผ๋ก ASP.NET Core ์ฝ๋ ๊ธฐ๋ฐ ์ธ๋ถ์์๋ ํ์ํ๋ค๋ ๋ ๋ง์ ์ฆ๊ฑฐ๋ฅผ ๋ณผ ๋๊น์ง๋ ์ด๊ฒ์ด ํ์ฌ๋ก์๋ ํ๋ฅญํ ์๋ฃจ์ ์ด ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
string
์ค๋ฒ๋ก๋๋ฅผ ์ ๊ฑฐํ ๋ ๊ฐ์ ๋ณผ ์ ์๋ค๊ณ ๋งํ๊ณ ์ถ์ต๋๋ค. ๋ณต์ก์ฑ์ ์ค์ด์ง ์๊ณ ์ฝ๋๋ฅผ ๋ ํจ์จ์ ์ผ๋ก ๋ง๋ค์ง ์์ผ๋ฉฐ StringComparison
์์ StringComparer
๋ฅผ ๋ฐํํ๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ ๊ฒ๊ณผ ๊ฐ์ด ๋ค๋ฅธ ์์ญ์ ๊ฐ์ ํ๋ ๋ฐ ๋ฐฉํด๊ฐ ๋์ง ์์ต๋๋ค. StringComparison
. .NET์ ํญ์ ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ๋ฅผ ์ฝ๊ฒ ๋ง๋๋ ๊ฒ์ ์ค์ ์ ๋์๊ธฐ ๋๋ฌธ์ ๊ตฌ๋ฌธ ์คํ์ _์ค์ํฉ๋๋ค_. ๋ํ ๊ฐ๋ฐ์๊ฐ ์ฌ๋ฐ๋ฅธ ์ผ์ ํ๊ณ ์ฑ๊ณต์ ๊ตฌ๋ฉ์ด์ ๋น ์ง๋๋ก ์๋ดํ๊ณ ์ถ์ต๋๋ค.
์ฐ๋ฆฌ๋ ๋ฌธ์์ด์ด ํน๋ณํ๊ณ ๋ฏฟ์ ์ ์์ ์ ๋๋ก ํํ๋ค๋ ๊ฒ์ ์ธ์ํด์ผ ํฉ๋๋ค. ๊ทธ๊ฒ๋ค์ ์ ๋ฌธํํ๋ ์ค๋ฒ๋ก๋๋ฅผ ์ถ๊ฐํจ์ผ๋ก์จ ์ฐ๋ฆฌ๋ ๋ ๊ฐ์ง๋ฅผ ๋ฌ์ฑํฉ๋๋ค:
๋ํ ์์์ ์ธ๊ธํ @Eilon ํ์ฅ ๋ฉ์๋์ ๊ฐ์ ์ผ๋ฐ์ ์ธ ์์ฉ๊ตฌ ๋์ฐ๋ฏธ๋ ์ข์ ๊ฒ์ด ์๋๋ผ ๋์ ๊ฒ์์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ๊ทธ ๊ฒฐ๊ณผ ๋์ฐ๋ฏธ ๋ฉ์๋๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ๋ ๋ฐ ์๊ฐ์ด ๋ญ๋น๋๊ณ ์ ๋๋ก ์ํ๋์ง ์์ผ๋ฉด ๋ถํ์ํ ์ฝ๋ ํฝ์ฐฝ๊ณผ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ฃผ์ ๊ด์ฌ์ฌ๊ฐ ํน์ ๋/์๋ฌธ์ string
๊ฒฝ์ฐ ๋ค์์ ์ด๋ป์ต๋๊น?
``` C#
๊ณต๊ฐ ๊ตฌ์กฐ์ฒด ํด์ ์ฝ๋: IEquatable
{
๊ณต๊ฐ HashCode ๊ฒฐํฉ
}
// ์ฉ๋ฒ
๋ฐํ HashCode.Combine(_numberField)
.Combine(_stringField, StringComparer.OrdinalIgnoreCase);
```
@terrajobst , ๋น์ ์ ํํ์ ์๋ฆฌํ ๊ฒ์
๋๋ค. ๋ ์ด์ GetHashCode
๋ช
์์ ์ผ๋ก ํธ์ถํ๊ฑฐ๋ ์ฌ์ฉ์ ์ ์ ๋น๊ต์๋ฅผ ์ฌ์ฉํ์ฌ ์ถ๊ฐ ๊ดํธ ์ธํธ๋ฅผ ์ค์ฒฉํ ํ์๊ฐ ์๋ค๋ ์ ์ด ๋ง์์ ๋ญ๋๋ค.
(ํธ์ง: ์ค๋ ๋์์ ์์ ์ธ๊ธํ @JonHanna ๋๋ถ์ ์ ๋ง ํฌ๋ ๋ง์ ๊ฐ์๋ฐ์ ? ๐ )
@JonHanna ์, null ์ ๋ ฅ๋ 0์ผ๋ก ํด์ํ ๊ฒ์ ๋๋ค.
์ฌ๊ธฐ์ ๋ํ๋ฅผ ๋ฐฉํดํด์ ์ฃ์กํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ ์ ํ์ ์ด๋์ ๋ฃ์ด์ผ ํฉ๋๊น? @mellinoe @ericstj @weshaggard , System.HashCode
์ ๊ฐ์ ์ด ์ ํ์ ๋ํ ์ ์ด์
๋ธ๋ฆฌ/ํจํค์ง๋ฅผ ๋ง๋ค๊ฑฐ๋ System.Runtime.Extensions
์ ๊ฐ์ ๊ธฐ์กด ์ด์
๋ธ๋ฆฌ์ ์ถ๊ฐํด์ผ ํฉ๋๊น? ๊ฐ์ฌ ํด์.
์ฐ๋ฆฌ๋ ์ต๊ทผ์ .NET Core์ ์ด์
๋ธ๋ฆฌ ๋ ์ด์์์ ์๋นํ ๋ฆฌํฉํ ๋งํ์ต๋๋ค. 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๊ฐ์ง ์ ํ์ผ๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ ๋์๊ฒ ์ด์ํ๊ฒ ๋ค๋ฆฝ๋๋ค. HashCode
๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ฐ๊ฒฐ์ ๋ง๋ค๊ณ ๋์ Hash
ํด๋์ค๋ก ์์ํด์ผ ํฉ๋๋ค.
์ฐจ๋ผ๋ฆฌ Create
๋ฉ์๋(๋๋ Seed
๋๋ Init
)๋ฅผ ์ถ๊ฐํ๊ณ ์ถ์ต๋๋ค.
๋๋ ๋ํ no-args ์ค๋ฒ๋ก๋ HashCode.Create().Combine(_field1).Combine(_field2)
์ถ๊ฐํ ๊ฒ์
๋๋ค.
@karelz , ๊ฐ์ ์ด๋ฆ์ด ์๋ ๊ฒฝ์ฐ ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ์ถ๊ฐํด์ผ ํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ๋งค๊ฐ๋ณ์๊ฐ ์๋ ์์ฑ์ new
๊ฐ ๋ ์์ฐ์ค๋ฝ๊ธฐ ๋๋ฌธ์ ์ ๊ณตํด์ผ ํฉ๋๋ค. ๊ฒ๋ค๊ฐ e๋ ๊ตฌ์กฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ ์ฌ๋๋ค์ด new HashCode().Combine
๋ฅผ ์ฐ๋ ๊ฒ์ ๋ง์ ์ ์์ต๋๋ค.
public override int GetHashCode()
{
return new HashCode()
.Combine(_field1)
...
}
์ด๊ฒ์ ํด์ ์ฝ๋์์ ์ง์ ์ด๊ธฐํํ๋ ๋์ 0 ๋ฐ _field1
์ ํด์ ์ฝ๋์ ์ถ๊ฐ ๊ฒฐํฉ์ ์ํํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉ ํ๊ณ ์๋
์ ์๋ 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) // ...
์ฒซ ๋ฒ์งธ์ ์ฅ์ ์ ์กฐ๊ธ ๋ ๊ฐ๊ฒฐํ๋ค๋ ๊ฒ์ ๋๋ค. ๋ ๋ฒ์งธ์ ์ฅ์ ์ ์ผ๊ด๋ ์ด๋ฆ ์ง์ ์ ๊ฐ์ง๋ฏ๋ก ์ฒซ ๋ฒ์งธ ํ๋์ ๋ํด ๋ค๋ฅธ ๊ฒ์ ์์ฑํ ํ์๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค.
๋ ๋ค๋ฅธ ๊ฐ๋ฅ์ฑ์ Combine
ํฉํ ๋ฆฌ๊ฐ ์๋ ์ ํ๊ณผ Combine
์ธ์คํด์ค๊ฐ ์๋ ์ ํ(๋๋ ์ฒซ ๋ฒ์งธ ์ ํ์ ํ์ฅ์ธ ๋ ๋ฒ์งธ ์ ํ)์ ๋ ๊ฐ์ง ๋ค๋ฅธ ์ ํ์
๋๋ค.
์ด๋ ๊ฒ์ด TBH๋ฅผ ์ ํธํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
@JonHanna , ์ธ์คํด์ค ์ค๋ฒ๋ก๋๊ฐ ํ์ฅ ๋ฉ์๋๋ผ๋ ๋ ๋ฒ์งธ ์์ด๋์ด๋ ํ๋ฅญํ๊ฒ ๋ค๋ฆฝ๋๋ค. ์ฆ, hc.Combine(obj)
์ด ๊ฒฝ์ฐ ์ ์ ๊ณผ๋ถํ: TryRoslyn ์ ์ ํํ๋ ค๊ณ ํฉ๋๋ค.
์์ ๋ช ๊ฐ์ง ์๊ฒฌ์ ์์์ ์ผ๋ก ์ ์ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ ์ํ๋๋ฐ, ์ด๋ ์ ์๊ฒ ์๊ธฐ์์ผ์ค๋๋ค...
๋ ผ๋ฆฌ๋ฅผ 2๊ฐ์ง ์ ํ์ผ๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ ๋์๊ฒ ์ด์ํ๊ฒ ๋ค๋ฆฝ๋๋ค. HashCode๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ฐ๊ฒฐ์ ๋ง๋ค๊ณ ๋์ Hash ํด๋์ค๋ก ์์ํด์ผ ํฉ๋๋ค.
์ฌ๋๋ค์ ์ด๋ค ์ฐ๊ฒฐ์ ํด์ผ ํ ๊น์? ๋จผ์ Hash
๋ฅผ ์๊ฐํ ๋ค์ ๊ฑฐ๊ธฐ์์ HashCode
์ด๋ํ ์ ์์ต๋๊น? ์๋ก์ด ์ ์ ํด๋์ค๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด ๋ฌธ์ ๊ฐ ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
๋ ผ๋ฆฌ๋ฅผ 2๊ฐ์ง ์ ํ์ผ๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ ๋์๊ฒ ์ด์ํ๊ฒ ๋ค๋ฆฝ๋๋ค. HashCode๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ฐ๊ฒฐ์ ๋ง๋ค๊ณ ๋์ Hash ํด๋์ค๋ก ์์ํด์ผ ํฉ๋๋ค.
์ต์์ ์ ํ์ HashCode
ํ๊ณ ๊ตฌ์กฐ์ฒด๋ฅผ ์ค์ฒฉํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด API์ "์ง์
์ "์ ํ๋์ ์ต์์ ์ ํ์ผ๋ก ์ ์งํ๋ฉด์ ์ํ๋ ์ฌ์ฉ์ ํ์ฉํ ์ ์์ต๋๋ค. ์:
``` C#
๋ค์์คํ์ด์ค ์์คํ
{
๊ณต๊ฐ ์ ์ ํด๋์ค HashCode
{
๊ณต๊ฐ ์ ์ HashCodeValue ๊ฒฐํฉ(int ํด์);
๊ณต๊ฐ ์ ์ HashCodeValue ๊ฒฐํฉ
๊ณต๊ฐ ์ ์ HashCodeValue ๊ฒฐํฉ
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
์์ฑ์ - ๋น์ ์ด ์ป์ ์์๋ Value
๋ฅผ ํตํด GetHashCode()
๋น์ ์ ์บ์คํ
ํ์ง ์์ผ๋ ค๋ฉด int
.
@justinvp ํ์ง๋ง ์ฒ์์ ๋ ๊ฐ์ ๊ฐ๋ณ ์ ํ์ ๊ฐ๋ ๋ฐ ๋ฌธ์ ๊ฐ ๋ฌด์์
๋๊น? ์ด ์์คํ
์ ์๋ฅผ ๋ค์ด LinkedList<T>
๋ฐ LinkedListNode<T>
์ ๋ํด ์ ์๋ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
๊ทธ๋ฌ๋ ์ฒ์์ ๋ ๊ฐ์ ๋ณ๋ ์ ํ์ ๊ฐ๋ ๋ฐ ๋ฌธ์ ๊ฐ ๋ฌด์์ ๋๊น?
๋ ๊ฐ์ง ์ต์์ ์ ํ์๋ ๋ ๊ฐ์ง ์ฐ๋ ค ์ฌํญ์ด ์์ต๋๋ค.
Hash
๋ฐ HashCode
๊ฒฝ์ฐ ์ด๋ ๊ฒ์ผ๋ก ์์ํฉ๋๊น? ๊ทธ ์ด๋ฆ์์ ๋ช
ํํ์ง ์์ต๋๋ค. LinkedList<T>
๋ฐ LinkedListNode<T>
ํ๋ฉด ์ด๋ ๊ฒ์ด ์ฃผ์ ์ง์
์ LinkedList<T>
์ด๊ณ ์ด๋ ๊ฒ์ด ๋์ฐ๋ฏธ์ธ์ง ๋งค์ฐ ๋ช
ํํฉ๋๋ค.System
๋ค์์คํ์ด์ค๋ฅผ ์ค์ผ์ํต๋๋ค. (1)๋งํผ ์ฐ๋ คํ ์ฌํญ์ ์๋์ง๋ง System
๋ค์์คํ์ด์ค์ ์๋ก์ด ๊ธฐ๋ฅ์ ๋
ธ์ถํ๋ ๊ฒ์ ๊ณ ๋ คํ ๋ ์ผ๋์ ๋์ด์ผ ํ ์ฌํญ์
๋๋ค.์ค์ฒฉ์ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ์ํํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
@justinvp
API์ "์ง์ ์ " ์ ํ์ ๋ฌด์์ ๋๊น? ์ด๋ฆ์ด Hash์ HashCode๋ผ๋ฉด ์ด๋ค ๊ฒ์ผ๋ก ์์ํ์๊ฒ ์ต๋๊น? ๊ทธ ์ด๋ฆ์์ ๋ช ํํ์ง ์์ต๋๋ค. LinkedList ์ฌ์ฉ
๋ฐ LinkedListNode ์ด๋ ๊ฒ์ด ์ฃผ์ ์ง์ ์ ์ธ LinkedList์ธ์ง๋ ๋งค์ฐ ๋ถ๋ช ํฉ๋๋ค. , ๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ ๋์ฐ๋ฏธ์ ๋๋ค.
์๊ฒ ์ต๋๋ค. ์ถฉ๋ถํ ์ง์ ์
๋๋ค. ์ค์ฒฉ ์ ํ์ด ์๋ Hash
๋ฐ HashValue
์ ํ์ ์ด๋ฆ์ ์ง์ ํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ๊ทธ๊ฒ์ ๋ ์ ํ ์ฌ์ด์ ์ข
์์ ์ธ ๊ด๊ณ๋ฅผ ์ถฉ๋ถํ ์๋ฏธํฉ๋๊น?
๊ทธ๋ ๊ฒ ํ๋ฉด ํฉํ ๋ฆฌ ๋ฉ์๋๊ฐ ํจ์ฌ ๊ฐ๊ฒฐํด์ง๋๋ค. Hash.Combine(field1).Combine(field2)
. ๋ํ ๊ตฌ์กฐ์ฒด ์ ํ ์์ฒด๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ฌ์ ํ โโ์ค์ฉ์ ์
๋๋ค. ์๋ฅผ ๋ค์ด ๋๊ตฐ๊ฐ ํด์ ๋ชฉ๋ก์ ์์งํ๊ณ ์ด๋ฅผ ๋
์์๊ฒ ์ ๋ฌํ๊ธฐ ์ํด 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
๊ฐ ์์ด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ ๋ชฉ์ ์ GetHash()
์๋๋ผ GetHashCode()
๊ตฌํ์ ๋๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์
๋๋ค.
๋๊ตฐ๊ฐ ํด์ ๋ชฉ๋ก์ ์์งํ๊ณ ์ด๋ฅผ ๋ ์์๊ฒ ์ ๋ฌํ๊ธฐ๋ฅผ ์ํ ์ ์์ต๋๋ค.
๋ชฉ๋ก ๋์ ์ฌ์ฉ๋ฉ๋๋ค. . ์ ํ์ ์ค์ฒฉํ๋ฉด ์ ์๋ํ์ง ์์ ์ ์์ต๋๋ค. (์ฌ์ง์ด ๋ชฉ๋ก ์ธ๋ป๋ณด๊ธฐ์๋ ๋ค์ ํผ๋ ์ค๋ฝ์ต๋๋ค).
์ด๊ฒ์ ๊ฐ๋ฅ์ฑ์ด ํฌ๋ฐํ ์ฌ์ฉ ์ฌ๋ก์ฒ๋ผ ๋ณด์ ๋๋ค. ๋์์ธ์ ์ต์ ํํด์ผ ํ๋์ง ํ์ ์ด ์์ง ์์ต๋๋ค.
์ค์ฒฉ ์ ํ์ด ์๋ ์์น๋ฅผ ์๊ฐํ ์ ์๋ ์ ์ผํ BCL API
TimeZoneInfo.AdjustmentRule
๋ฐ TimeZoneInfo.TransitionTime
๋ ์๋์ ์ผ๋ก ์ค์ฒฉ ์ ํ์ผ๋ก ์ถ๊ฐ๋ BCL์ ์์
๋๋ค.
@justinvp
์ง์ ์ API์ ์ด๋ฆ์ HashCode๊ฐ ์์ด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ ๋ชฉ์ ์ GetHash()๊ฐ ์๋๋ผ GetHashCode() ๊ตฌํ์ ๋๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.
๐ ์๊ฒ ์ต๋๋ค.
์ข ๋ ์๊ฐํด ๋ดค์ต๋๋ค. ์ค์ฒฉ๋ ๊ตฌ์กฐ์ฒด๋ฅผ ๊ฐ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ผ๋ก ๋ณด์
๋๋ค. ๋น์ ์ด ์ธ๊ธํ๋ฏ์ด ๋๋ถ๋ถ์ ์ฌ๋๋ค์ ์ค์ ์ ํ์ ๋ณด์ง ๋ชปํ ๊ฒ์
๋๋ค. ํ ๊ฐ์ง๋ง: ์ ํ์ HashCodeValue
๋์ Seed
๋ผ๊ณ ํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ฆ์ ์ปจํ
์คํธ๋ ํฌํจํ๋ ํด๋์ค์ ์ด๋ฏธ ์์๋์ด ์์ต๋๋ค.
์ ์๋ 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);
Seed์ ๋ฌธ์ ๋ ๊ธฐ์ ์ ์ผ๋ก ์ฒซ ๋ฒ์งธ ๊ฒฐํฉ ํ ์ข ์๊ฐ ์๋๋ผ๋ ๊ฒ์ ๋๋ค.
๊ทธ๊ฒ์ ์๋ก์ด ์จ์์ ์์ฐํ๋ ๋ค์ ๊ฒฐํฉ์ ์จ์์ ๋๋ค.
๋์ public readonly int Value๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ํ ๋ฐ๋ ๋๋ ๊ตฌํ ๋ฌธ์ ๊ฐ ์์ต๋๊น?
์์? int Value { get; }
๋ ๋ณด๋ค ๊ด์ฉ์ ์ด๋ฉฐ ์ฝ๊ฒ ์ธ๋ผ์ธ๋ ์ ์์ต๋๋ค.
๊ทธ๊ฒ์ ์๋ก์ด ์จ์์ ์์ฐํ๋ ๋ค์ ๊ฒฐํฉ์ ์จ์์ ๋๋ค.
๋ฌ๋ชฉ์ด ์๋๊ฒ ์ต๋๊น? ;)
@jamesqo ๋ด ๊ฒฝํ์
ํธ์ง: ๋ํ ํด๋น ๊ตฌ์กฐ์ฒด๊ฐ ์ค์ ๋ก ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ๋ค๋ ์์ด๋์ด๋ ์ถ์งํฉ๋๋ค.
๋ด ๊ฒฝํ์ ๋ฐ๋ฅด๋ฉด ๋ณต์กํ ์ฝ๋ ์์ฑ์ผ๋ก ๋๋ฌ์ธ์ฌ ์์ผ๋ฉด ํ๋๋ณด๋ค ๋ ๋์ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒฝํฅ์ด ์์ต๋๋ค(๊ทธ ์ค์์ ์ธ๋ผ์ธ์ด ์๋).
์๋ ๊ตฌํ ์์ฑ์ด ํญ์ ์ธ๋ผ์ธ๋์ง ์๋ ๋จ์ผ ๋น ๋๋ฒ๊ทธ ๋น๋๋ฅผ ์ฐพ์ผ๋ฉด ์ด๋ JIT ๋ฌธ์ ์ด๋ฉฐ ํ์คํ ์์ ํด์ผ ํฉ๋๋ค.
๋ํ ๊ตฌ์กฐ์ฒด์ ์๋ ๋จ์ผ int์ ์ฝ๊ธฐ ์ ์ฉ ํ๋๋ ๋ ์ง์คํฐ์์ ๋ฐ๋ก ๋ณํ๋ฉ๋๋ค.
์ฝ๊ธฐ ์ ์ฉ์ด๋ผ๊ณ ์๊ฐํ ์ ์๊ธฐ ๋๋ฌธ์ ํ์ฉ๋ ์ ์๋ ์ต์ ํ๊ฐ ์์ต๋๋ค.
์ด ๊ตฌ์กฐ์ฒด์ ์ง์ ํ๋๋ ์ฝ๊ธฐ ์ ์ฉ์ ๋๋ค. API๋ ์ ๊ทผ์๊ฐ ๋ ๊ฒ์ ๋๋ค.
์์ฑ์ ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ์ด ์ ํ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
@jamesqo ์ฐพ์ผ๋ฉด ๋ช ์ฌํ๊ฒ ์ต๋๋ค. ์ฑ๋ฅ์ ๋ฏผ๊ฐํ ์ฝ๋์ ๊ฒฝ์ฐ ๊ทธ ๋๋ฌธ์ ๋ ์ด์ ์์ฑ์ ์ฌ์ฉํ์ง ์์ต๋๋ค(์ด ์์ ์์ ๊ทผ์ก ๋ฉ๋ชจ๋ฆฌ).
์ค์ฒฉ๋ ๊ตฌ์กฐ์ฒด๋ฅผ "Seed"๊ฐ ์๋ "State"๋ผ๊ณ ๋ถ๋ฅด๋ ๊ฒ์ ๊ณ ๋ คํ ์ ์์ต๋๊น?
@ellismg ๋ฌผ๋ก ์ ๋๋ค. ์ ์ ๊ฐ์ฌํฉ๋๋ค. ๋๋ ๋ด๋ถ ๊ตฌ์กฐ์ฒด์ ๋ํ ์ข์ ์ด๋ฆ์ ์๊ฐํด๋ด๊ธฐ ์ํด ๊ณ ๊ตฐ๋ถํฌํ์ต๋๋ค.
@karelz ์ด API๋ ๋ง์นจ๋ด ์ฌ์ฉํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ฒ์๋ ๋ชจ๋ ๊ฒ์ด ์ปดํ์ผ๋๋์ง ํ์ธํ์ต๋๋ค. ์๋ฌด๋ ์ด์๋ฅผ ์ ๊ธฐํ์ง ์๋ ํ ์ด์ ๋ํ ๊ตฌํ ์์ ์ ์์ํ๊ฒ ์ต๋๋ค.
@jamesqo @JonHanna ์ ์ฐ๋ฆฌ๋ ํ์ ์์ Combine<T>(T obj)
๋์ Combine(object o)
?
์ฝค๋ฐ์ธ์ด ํ์ํ ์ด์
Combine(object o) ๋์ (T obj)?
์ธ์คํด์ค๊ฐ ๊ตฌ์กฐ์ฒด์ธ ๊ฒฝ์ฐ ํ์๋ ํ ๋นํฉ๋๋ค.
์, ์ค๋ช ๊ฐ์ฌํฉ๋๋ค.
์ค์ฒฉ ์ ํ์ ๋์์ธ์ ๋ณต์กํ๊ฒ ๋ง๋ค๊ธฐ ๋๋ฌธ์ ์ข์ํ์ง ์์ต๋๋ค. ๊ทผ๋ณธ์ ์ธ ๋ฌธ์ ๋ ์ ์ ๋ฐ ๋น์ ์ ์ด๋ฆ์ ๋์ผํ๊ฒ ์ง์ ํ ์ ์๋ค๋ ๊ฒ์
๋๋ค. ์ ์ ์ ์ ๊ฑฐํ๊ฑฐ๋ ์ด๋ฆ์ ๋ณ๊ฒฝํ๋ ๋ ๊ฐ์ง ์ต์
์ด ์์ต๋๋ค. Create
์ด๋ฆ์ ๋ฐ๊พธ๋ ๊ฒ์ด ๊ธฐ๋ณธ ์์ฑ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋น๊ตํ์ฌ ์๋นํ ์ฝ๊ธฐ ์ฌ์ด ์ฝ๋๋ฅผ ์์ฑํ๋ฏ๋ก ๊ฐ์ฅ ์๋ฏธ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ฐ๋ ฅํ ๋ฐ๋๊ฐ ์๋ ํ ์ฐ๋ฆฌ๊ฐ ๊ฒฐ์ ํ ๋์์ธ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
```C#
๋ค์์คํ์ด์ค ์์คํ
{
๊ณต๊ฐ ๊ตฌ์กฐ์ฒด ํด์ ์ฝ๋: IEquatable
{
๊ณต๊ฐ ์ ์ HashCode Create(int hashCode);
๊ณต๊ฐ ์ ์ HashCode ๋ง๋ค๊ธฐ
๊ณต๊ฐ ์ ์ HashCode ๋ง๋ค๊ธฐ
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()
.
operator-new๊ฐ ์๋ ๋ฒ์ ์ ํ์ฉํ๊ณ ๋์ค์ Create๋ฅผ ๋ถํธ์คํธ๋ํผ๋ก ์ ๋ง๋ก ์ํ๋ค๋ ๊ฒฐ์ ์ ๋ฐฐ์ ํ์ง ์๊ธฐ ๋๋ฌธ์... ::shrug::.
์ด๊ฒ์ด ๋ด ๋ฐ๋ฐ์ ์ ์ฒด ๋ฒ์์ ๋๋ค(๋ณ๋ก ๋ง์ง๋ ์์).
FWIW Empty
/ Zero
๋์ Create
ํฌํํ๊ฒ ์ต๋๋ค. ๋ชจ๋ ๊ฒ์ Empty
/ Zero
์ค๋จํ๋ ๊ฒ๋ณด๋ค ์ค์ ๊ฐ์ผ๋ก ์์ํ๊ณ ์ถ์ต๋๋ค. ๊ธฐ๋ถ์ด ์ด์ํ๋ค/์ด์ํด ๋ณด์ธ๋ค.
๊ทธ๊ฒ์ ๋ํ ๊ฐ๋ํ ์ข ์ ๊ฒฝํฅ์ด ์๋ 0์ผ๋ก ํ์ข ํ๋ ์ฌ๋๋ค์ ๋๋ด์ํต๋๋ค.
๋๋ ๋น์ด์๋ ๊ฒ๋ณด๋ค ๋ง๋ค๊ธฐ๋ฅผ ์ ํธํฉ๋๋ค. ๊ทธ๊ฒ์ ๋ด๊ฐ ๊ทธ๊ฒ์ ๋ํด ์ด๋ป๊ฒ ์๊ฐํ๋์ง ์์ํดํฉ๋๋ค. ํด์ ์ฝ๋๋ฅผ ๋ง๋ค๊ณ ์ถ๊ฐ ๊ฐ์ ํผํฉํ๊ณ ์ถ์ต๋๋ค. ์ค์ฒฉ ์ ๊ทผ ๋ฐฉ์๋ ๊ด์ฐฎ์ต๋๋ค.
๋ด๊ฐ ๊ทธ๊ฒ์ Empty๋ผ๊ณ ๋ถ๋ฅด๋ ๊ฒ์ ์ข์ ์๊ฐ์ด ์๋๋ผ๊ณ ๋งํ๋ ค๊ณ ํ์ง๋ง(๊ทธ๋ฆฌ๊ณ ์ด๋ฏธ ๋งํ ๋ฐ ์์), ์ธ ๋ฒ์งธ ์๊ฐ ํ์ ๋๋ ์ฌ์ ํ ๊ทธ๊ฒ์ด ๋์ ํด๊ฒฐ์ฑ ์ด ์๋๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋น๋์ ๊ฐ์ ๊ฒ์ ์ด๋ป์ต๋๊น? ์ฌ์ ํ 0์ ์ฌ์ฉํ ์๋ ์์ง๋ง ๋จ์ด๋ ๋ฐ๋ก ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํ์ง ์์ต๋๋ค.
@JonHanna ๋ช
ํํ ํ๊ธฐ ์ํด: Create
๋ํ ํฌํ๋ฅผ ์๋ฏธํ์ต๋๊น?
๊ทธ๋ฆฌ๊ณ ๋ค ๋ฒ์งธ๋ Create ๋์ With์ ๋ํด ์๊ฐํ์ต๋๋ค.
HashCode.With(a).Combine(b). ๊ฒฐํฉ(c)
์ต์ ํ ๋ก ์ ๊ธฐ๋ฐ์ผ๋ก ํ ์ฌ์ฉ ์( Create
๊ฐ ๋์ฒด ์ด๋ฆ์ผ๋ก ๋์ฒด๋ ์ ์์):
```c#
๊ณต๊ฐ ์ฌ์ ์ 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 ์ผ๊ด์ฑ ์๋ ์ฝ๋ + ๋ ๋ง์ ์งํ ์ผ๋ก ์ด์ด์ง ๊ฒ์ ๋๋ค. ๋ ์ผ๋ฐ์ ์ธ ์กฐํฉ์ผ๋ก ์๊ฐํฉ๋๋ค. ๊ทธ๊ฒ์ด ๋ฐ๋์งํ ๊ฒ์ผ๋ก ํ๋ช ๋๋ฉด ์ฐ๋ฆฌ๋ ํญ์ ๋ค๋ฅธ ๋ฌธ์ ์์ ์ด๊ฒ์ ๋ค์ ๋ ผ์ํ ์ ์์ต๋๋ค.
๊ทธ๋งํ ๊ฐ์น๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ต์ํ ์ฌ์ฉ๋ฒ์์๋ ์๋ ์ ์๋ ๋ฒ์ ์ ์ ํธํฉ๋๋ค(์ฝ๋ ํฌ๊ธฐ, ์งํ ๋ฑ์ ๊ดํ ์ฃผ์์ ํ์คํ์ง ์์). ๋ค๋ฅธ arity์ ๋ช ๊ฐ์ง ์ค๋ฒ๋ก๋๋ฅผ ์ฌ์ฉํ์ฌ ํ๋์ ๋ฉ์๋๋ก ํํ๋ ์ ์๋ ๋ฌด์ธ๊ฐ์ ๋ํด ์ถ๊ฐ ๊ตฌ์กฐ์ 10๊ฐ ์ด์์ ๋ค๋ฅธ ๋ฉค๋ฒ๋ฅผ ๊ฐ๋ ๊ฒ์ ๊ณผ์์ฒ๋ผ ๋ณด์ ๋๋ค. ๋๋ ๋ํ ์ผ๋ฐ์ ์ผ๋ก ์ ์ฐฝํ ์คํ์ผ API์ ํฌ์ด ์๋๋ฏ๋ก ์๋ง๋ ๊ทธ๊ฒ์ด ๋ด ์๊ฒฌ์ ์ํฅ์ ๋ฏธ์น ๊ฒ์ ๋๋ค.
์กฐ๊ธ ์ด์ํ๊ณ ์์ง ๋ด ๊ธฐ๋ถ์ด ์ด๋ค์ง ํ์ ์ด ์์ง ์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ์ธ๊ธํ์ง ์์ ์์ ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ฌ๊ธฐ์ ๋ค๋ฅธ ์์ด๋์ด๊ฐ ์์ต๋๋ค. ๋ชจ๋ ๋์์ด ๊ณ ๋ ค๋์๋์ง ํ์ธํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค...
์ ์ฌํ Add
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ASP.NET Core์ ๋ณ๊ฒฝ ๊ฐ๋ฅํ HashCodeCombiner
"๋น๋" ๋ผ์ธ์ ๋ฐ๋ผ ๋ฌด์ธ๊ฐ๋ฅผ ์ํํ์ง๋ง ์ปฌ๋ ์
์ด๋์
๋ผ์ด์ ๊ตฌ๋ฌธ์ ๋ํ ์ง์๋ ํฌํจํ๋ค๋ฉด?
์ฉ๋ฒ:
```c#
๊ณต๊ฐ ์ฌ์ ์ int GetHashCode() =>
์๋ก์ด ํด์ ์ฝ๋ { _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();
}
}
์ปฌ๋ ์
์ด๋์
๋ผ์ด์ ๊ตฌ๋ฌธ์ ํ์ฑํํ๋ ค๋ฉด ์ต์ํ ํ๋์ Add
๋ฉ์๋์ ํจ๊ป IEnumerable
๋ฅผ ๊ตฌํํด์ผ ํฉ๋๋ค. IEnumerable
๋ ๋ช
์์ ์ผ๋ก ๊ตฌํํ์ฌ Intellisense์์ ์จ๊ธฐ๊ณ GetEnumerator
๋ NotSupportedException
๋ฅผ ๋์ง๊ฑฐ๋ ํด์ ์ฝ๋ ๊ฐ์ ์ด๊ฑฐ ๊ฐ๋ฅํ ๋จ์ผ ๊ฒฐํฉ ํญ๋ชฉ์ผ๋ก ๋ฐํํ ์ ์์ต๋๋ค. ๊ทธ๊ฒ์ ์ฌ์ฉํ์ญ์์ค (๋๋ฌธ ์ผ์
๋๋ค).
@justinvp , ํฅ๋ฏธ๋ก์ด ์์ด๋์ด๊ฐ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ์ ์คํ๊ฒ ๋์ํ์ง ์์ต๋๋ค. HashCode
๋ ๊ฐ๋ณ ๊ตฌ์กฐ์ฒด๊ฐ ์๋ ๋ฌธ์ ๋ฅผ ํผํ๊ธฐ ์ํด ๋ถ๋ณ์ผ๋ก ์ ์ง๋์ด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ํ ์ด๋ฅผ ์ํด IEnumerable
๋ฅผ ๊ตฌํํด์ผ ํ๋ ๊ฒ์ ๋ค์ ์ธ๊ณต์ ์ด๊ฑฐ๋ ๋ถ์์ ํด ๋ณด์
๋๋ค. ๋๊ตฐ๊ฐ ํ์ผ์ using System.Linq
์ง์๋ฌธ์ด ์๋ ๊ฒฝ์ฐ HashCode
์์ ์ ์ ๋ฃ์ผ๋ฉด Cast<>
๋ฐ OfType<>
๊ฐ ํ์ฅ ๋ฉ์๋๋ก ํ์๋ฉ๋๋ค. ๋๋ ์ฐ๋ฆฌ๊ฐ ํ์ฌ ์ ์์ ๋ ๊ฐ๊น์ด ๋ค๊ฐ๊ฐ์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
@jamesqo , ๋์ํฉ๋๋ค. ๋ฐ๋ผ์ ์ธ๊ธํ๋ ๊ฒ์กฐ์ฐจ ์ฃผ์ ํฉ๋๋ค. ๋ด๊ฐ ๊ทธ๊ฒ์ ๋ํด ์ข์ํ๋ ์ ์ผํ ๊ฒ์ ์ฌ์ฉ๋ฒ์ด ์ฒด์ธ๋ณด๋ค ๊นจ๋ํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ปฌ๋ ์ ์ด๋์ ๋ผ์ด์ ๊ฐ ์ํ ์ฌ์ฉ๋ฒ์ ๋ณด์ง ์๊ณ ๋ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ด ๋ถ๋ช ํ์ง ์๊ธฐ ๋๋ฌธ์ ๊ทธ ์์ฒด๊ฐ ๋ ๋ค๋ฅธ ๋จ์ ์ ๋๋ค.
@MadsTorgersen , @jaredpar , ์ปฌ๋ ์
์ด๋์
๋ผ์ด์ ์ IEnumerable ๊ตฌํ์ด ํ์ํ ์ด์ \
@jamesqo , ๋๋ ์ด๊ฒ์ ๋ถ๋ณ(IEnumerable์ด ์๋)์ผ๋ก ์ ์งํ๋ ๊ฒ์ด ๋ซ๋ค๋ ๋ฐ ๋์ํฉ๋๋ค.
@mellinoe ๋๋ ๊ทธ๊ฒ์ด ๊ฐ๋จํ ๊ฒฝ์ฐ๋ฅผ ์ฝ๊ฐ ๋ ๋จ์ํ๊ฒ ๋ง๋ค ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง, ๊ทธ ์ด์์ ๋ ๋ณต์กํ๊ฒ ๋ง๋ค ์๋ ์์ต๋๋ค.
๊ทธ๊ฒ์ ํฌํจ:
์ด ์ฃผ์ ์ ๋ํด ์ด์ ์ ๊ฒ์๋ ASP.NET์ ์ฝ๋๋ฅผ ๊ณ ๋ คํ์ญ์์ค(ํ์ฌ ์ ์์ผ๋ก ์ ๋ฐ์ดํธ๋จ).
```c#
var ํด์ ์ฝ๋ = ํด์ ์ฝ๋
.Create(IsMainPage)
.Combine(ViewName, StringComparer.Ordinal)
.Combine(์ปจํธ๋กค๋ฌ ์ด๋ฆ, StringComparer.Ordinal)
.Combine(์์ญ ์ด๋ฆ, StringComparer.Ordinal);
if (ViewLocationExpanderValues โโ!= null)
{
foreach(ViewLocationExpanderValues์ var ํญ๋ชฉ)
{
ํด์์ฝ๋ = ํด์์ฝ๋
.Combine(item.Key, StringComparer.Ordinal)
.Combine(ํญ๋ชฉ.๊ฐ, StringComparer.Ordinal);
}
}
๋ฐํ ํด์ ์ฝ๋;
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 @ericlippert์ ๋ฐ๋ฅด๋ฉด์ ์ธ์ด ํ๋ก๊ทธ๋๋ฐ์ C #์์ ๋
ธํธ 1, ๊ทธ๊ฒ์ ์ปฌ๋ ์
์ด๋์
๋ผ์ด์ ์ด๊ธฐ ๋๋ฌธ์ (๋น์ฐํ)ํ์ง ์ฐ์ฐ์ ๋ํ ์์ง ์์ฑ์์ํ ๋ฌธ๋ฒ ์คํ, (์ด๋ผ๋ ๋ฐฉ๋ฒ์ ๋ค๋ฅธ ์ผ๋ฐ์ ์ธ ์ฌ์ฉํ๋ค ๋ ์ด๋ช
์ด๋ค Add
).
1 Google ๋์์ ์๋ ๋ฐฉ์์ผ๋ก ์ธํด ํด๋น ๋งํฌ๊ฐ ๋ชจ๋ ์ฌ๋์๊ฒ ์๋ํ์ง ์์ ์ ์์ต๋๋ค.
@KrzysztofCwalina , IEnumerable<T>
๊ฐ ์๋ ์ผ๋ฐ์ด ์๋ IEnumerable
๊ฐ ํ์ํฉ๋๋ค.
@svick , ์์ ์ฒซ ๋ฒ์งธ ์์์ ์ฌ์ํ ๋ํธ: .Combine
๋ํ ์ฒซ ๋ฒ์งธ ํธ์ถ์ ํ์ฌ ์ ์์์ .Create
์
๋๋ค. ์ค์ฒฉ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ์ง ์๋ ํ.
@svic
๊ทธ๊ฒ์ ๋ํ ๊ทธ ์ด์์ ๊ฒ์ ๋ ๋ณต์กํ๊ฒ ๋ง๋ค ๊ฒ์ ๋๋ค(๊ทธ๋ฆฌ๊ณ ๋ฌด์์ด ์ณ์ ์ผ์ธ์ง์ ๋ํด ๋ ๋ช ํํด์ง๋๋ค)
๋ ๋ฒ์งธ ์์ ๋ ์ ์ฒด์ ์ผ๋ก ์ฒซ ๋ฒ์งธ ์์ ์ ๊ฑฐ์ ๋ค๋ฅด์ง ์์ผ๋ฉฐ ๋ ๋ณต์กํ IMO๋ ์๋๋๋ค. ๋ ๋ฒ์งธ/์๋ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ๋ง์ ํด์ ์ฝ๋๋ฅผ ์ ๋ฌํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค(์ฒซ ๋ฒ์งธ ๋งค๊ฐ ๋ณ์๋ ์ค์ ๋ก IsMainPage.GetHashCode()
์ฌ์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค). ๊ทธ๋์ ๋์๊ฒ๋ ๊ฐ๋จํด ๋ณด์
๋๋ค. ํ์ง๋ง ์ ๊ฐ ์์์ ์ํ๋ ๊ฒ ๊ฐ์์ ์๋์ ๋ฐฉ์์ ๊ณ ์งํ์ง๋ ์๊ฒ ์ต๋๋ค. ๋๋ ๊ฐํ ์๊ฒฌ์ด ์์ต๋๋ค. ์ด ๋ ๊ฐ์ง ์๋ ๋ชจ๋ ๋์๊ฒ ์ถฉ๋ถํ ํฉ๋ฆฌ์ ์ผ๋ก ๋ณด์
๋๋ค.
@justinvp ๊ฐ์ฌํฉ๋๋ค. ์ ๋ฐ์ดํธ๋์์ต๋๋ค. (๋๋ ์ฒซ ๋ฒ์งธ ๊ฒ์๋ฌผ์ ์ฒซ ๋ฒ์งธ ์ ์์ผ๋ก ๊ฐ๊ณ ๊ทธ๊ฒ์ด ๊ตฌ์์ด๋ผ๋ ๊ฒ์ ๊นจ๋ซ์ง ๋ชปํ์ต๋๋ค. ๋๊ตฐ๊ฐ๊ฐ ์ ๋ฐ์ดํธํด์ผ ํ ๊ฒ์ ๋๋ค.)
@mellinoe ๋ฌธ์ ๋ ์ค์ ๋ก ๋ ๋ฒ์งธ๊ฐ ๋ฏธ๋ฌํ ๋ฒ๊ทธ๋ฅผ ์์ฑํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ ์ฐ๋ฆฌ ํ๋ก์ ํธ ์ค ํ๋์ ์ค์ ์ฝ๋์ ๋๋ค.
[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 ์์ค์์ ์ ์ฒด ์ค๋ฅ ์งํฉ์ ์ ๊ฑฐํ ์ ์์ต๋๋ค.
๋๋ ์ฒซ ๋ฒ์งธ ๊ฒ์๋ฌผ์ ์ฒซ ๋ฒ์งธ ์ ์์ผ๋ก ๊ฐ๊ณ ๊ทธ๊ฒ์ด ๊ตฌ์์ด๋ผ๋ ๊ฒ์ ๊นจ๋ซ์ง ๋ชปํ์ต๋๋ค. ๋๊ตฐ๊ฐ๊ฐ ์ ๋ฐ์ดํธํด์ผ ํ ๊ฒ์ ๋๋ค.
์๋ฃ.
BTW: ์ด ์ ์์ ํนํ ํฌํ๋ฅผ ์ถ์ ํ๊ธฐ๊ฐ ๋งค์ฐ ์ด๋ ต์ต๋๋ค... ๋๋ฌด ๋ง์ ๋ณํ(์ข์ ๊ฒ ๊ฐ์์ ;-))
@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
๊ทธ๊ฒ์ ๋ํ ๊ฐ๋ํ ์ข ์ ๊ฒฝํฅ์ด ์๋ 0์ผ๋ก ํ์ข ํ๋ ์ฌ๋๋ค์ ๋๋ด์ํต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ ํํ๋ ํด์ฑ ์๊ณ ๋ฆฌ์ฆ์ ์ค๋๋ 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()๋ฅผ ํธ์ถํ์ฌ ์ป์ ๊ฐ๋ฅ์ฑ์ด ์๋ ํด์ ์ฝ๋๊ฐ ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋งค๊ฐ๋ณ์์ ์ด๋ฆ์ ํด์ ๋์ hashCode๋ก ์ง์ ํด์ผ ํฉ๋๊น?
int ๋งค๊ฐ๋ณ์ hash
๋ฐ HashCode
๋งค๊ฐ๋ณ์ hashCode
์ด๋ฆ์ ์ง์ ํ๊ณ ์ถ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ค์ ์๊ฐํด ๋ณด๋ฉด hashCode
๊ฐ ๋ ์ข์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์๋ํ๋ฉด ์ธ๊ธํ ๋๋ก hash
๊ฐ ๋ค์ ๋ชจํธํ๊ธฐ ๋๋ฌธ์
๋๋ค. 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์ ์์ด์ผ ํฉ๋๋ค.
์ถ์ : ๋งค์ฐ ํฅ๋ฏธ๋ก์ด ์ค๋ ๋!! ์ ํ์ด! ๐
@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์์ ๋น์ ์ด ์๋์ผ๋ก/์ค์๋ก arg name obj
์ value
๋ก ๋ณ๊ฒฝํ๋ค๋ ๊ฒ์ ์์์ฐจ๋ ธ์ต๋๋ค. IMO๊ฐ ์ป๋ ๊ฒ์ ๋ ์ ์บก์ฒํ๋ obj
๋ค์ ์ ํํ์ต๋๋ค. ์ด๋ฆ value
๋ ์ด ์ปจํ
์คํธ์์ "int" ํด์ ๊ฐ ์์ฒด์ ๋ ๊ด๋ จ์ด ์์ต๋๋ค.
ํ์ํ ๊ฒฝ์ฐ arg ์ด๋ฆ์ ๋ํด ์ถ๊ฐ ํ ๋ก ์ ํ ์ ์์ง๋ง ์๋์ ์ผ๋ก ๋ณ๊ฒฝํ๊ณ ๋ง์ง๋ง์ผ๋ก ์น์ธ๋ ์ ์๊ณผ์ ์ฐจ์ด์ ์ ์ถ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
์๋จ์ ์ ์์ ์ ๋ฐ์ดํธํ์ต๋๋ค. ๋๋ ๋ํ ์ ์์์ ๋ง์ง๋ง ์น์ธ ๋ฒ์ ์ ๋ํด diff๋ฅผ ํธ์ถํ์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ ํํ๋ ํด์ฑ ์๊ณ ๋ฆฌ์ฆ์ ์ค๋๋ HashHelpers์์ ์ฌ์ฉ๋๋ ๊ฒ๊ณผ ๋์ผํฉ๋๋ค.
๋ชจ๋ ๊ณณ์์ ์ฌ์ฉํด์ผ ํ๋ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ ํํ๋ ๊ฒ์ด ์ข์ ์๊ณ ๋ฆฌ์ฆ์ธ ์ด์ ๋ ๋ฌด์์ ๋๊น? ๊ฒฐํฉ๋๋ ํด์์ฝ๋์ ๋ํด ์ด๋ค ๊ฐ์ ์ ํฉ๋๊น? ๋ชจ๋ ๊ณณ์์ ์ฌ์ฉํ๋ฉด DDoS ๊ณต๊ฒฉ์ ์๋ก์ด ๊ธธ์ ์ด ์ ์์ต๋๊น? (๊ณผ๊ฑฐ์ ๋ฌธ์์ด ํด์ฑ์ผ๋ก ์ธํด ํ์์ ์ ์์ต๋๋ค.)
ASP.NET Core์ ๋ณ๊ฒฝ ๊ฐ๋ฅํ HashCodeCombiner "๋น๋" ๋ผ์ธ์ ๋ฐ๋ผ ๋ฌด์ธ๊ฐ๋ฅผ ํ๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
์ฌ์ฉํ๊ธฐ์ ์ ํฉํ ํจํด์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ข์ ๋ฒ์ฉ ํด์์ฝ๋ ๊ฒฐํฉ๊ธฐ๋ ์ผ๋ฐ์ ์ผ๋ก ํด์์ฝ๋ ์์ฒด์ ๋ง๋ ๊ฒ๋ณด๋ค ๋ ๋ง์ ์ํ๋ฅผ ์ฌ์ฉํ ์ ์์ง๋ง ๋ ํฐ ๊ตฌ์กฐ์ฒด๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ ์ฑ๋ฅ ๋ฌธ์ ์ด๊ธฐ ๋๋ฌธ์ ์ ์ฐฝํ ํจํด์ด ๋ฌด๋์ง๋๋ค.
๋ชจ๋ ๊ณณ์์ ์ฌ์ฉํด์ผ ํ๋ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ ํํ๋ ๊ฒ์ด ์ข์ ์๊ณ ๋ฆฌ์ฆ์ธ ์ด์ ๋ ๋ฌด์์ ๋๊น?
๋ชจ๋ ๊ณณ์์ ์ฌ์ฉํด์๋ ์๋ฉ๋๋ค. https://github.com/dotnet/corefx/issues/8034#issuecomment -260790829์์ ๋ด ์๊ฒฌ์
๊ฒฐํฉ๋๋ ํด์์ฝ๋์ ๋ํด ์ด๋ค ๊ฐ์ ์ ํฉ๋๊น? ๋ชจ๋ ๊ณณ์์ ์ฌ์ฉํ๋ฉด DDoS ๊ณต๊ฒฉ์ ์๋ก์ด ๊ธธ์ ์ด ์ ์์ต๋๊น?
ํ์ฌ ํด์์ ํ ๊ฐ์ง ๋ฌธ์ ๋ hash(0, x) == x
์
๋๋ค. ๋ฐ๋ผ์ ์ผ๋ จ์ null ๋๋ 0์ด ํด์์ ์
๋ ฅ๋๋ฉด 0์ผ๋ก ์ ์ง๋ฉ๋๋ค. ์ฝ๋๋ฅผ ์ฐธ์กฐํ์ญ์์ค. ์ด๊ฒ์ null์ด ๊ณ์ฐ๋์ง ์๋๋ค๋ ๋ง์ ์๋์ง๋ง ์ด๊ธฐ null์ ๊ณ์ฐ๋์ง ์์ต๋๋ค. 0์์ 0์ผ๋ก ๋งคํํ๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด ๋ง๋ฒ ์์๋ฅผ ์ถ๊ฐํ๋ here ์ ๊ฐ์ด ๋ ๊ฐ๋ ฅํ(๊ทธ๋ฌ๋ ์ฝ๊ฐ ๋ ๋น์ผ) ๊ฒ์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ๊ณ ์์ต๋๋ค.
์ฌ์ฉํ๊ธฐ์ ์ ํฉํ ํจํด์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ข์ ๋ฒ์ฉ ํด์์ฝ๋ ๊ฒฐํฉ๊ธฐ๋ ์ผ๋ฐ์ ์ผ๋ก ํด์์ฝ๋ ์์ฒด์ ๋ง๋ ๊ฒ๋ณด๋ค ๋ ๋ง์ ์ํ๋ฅผ ์ฌ์ฉํ ์ ์์ง๋ง ๋ ํฐ ๊ตฌ์กฐ์ฒด๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ ์ฑ๋ฅ ๋ฌธ์ ์ด๊ธฐ ๋๋ฌธ์ ์ ์ฐฝํ ํจํด์ด ๋ฌด๋์ง๋๋ค.
๋ชจ๋ ์ฌ์ฉ ์ฌ๋ก์ ์ ํฉํ๋๋ก ์๋ํ๋ ํฐ ๊ตฌ์กฐ์ฒด ํฌ๊ธฐ๋ฅผ ๊ฐ์ง ๋ฒ์ฉ ๊ฒฐํฉ๊ธฐ๊ฐ ์์ด์ผ ํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ๋์ ๋ชจ๋ int ํฌ๊ธฐ( FnvHashCode
๋ฑ)์ด๊ณ ๋ชจ๋ ๊ณ ์ ํ Combine
๋ฉ์๋๊ฐ ์๋ ๋ณ๋์ ํด์ ์ฝ๋ ์ ํ์ ๊ตฌ์ํ์ต๋๋ค. ๊ฒ๋ค๊ฐ ์ด๋ฌํ "๋น๋" ์ ํ์ ์ ๋ฌ๋์ง ์๊ณ ์ด์จ๋ ๋์ผํ ๋ฐฉ๋ฒ์ผ๋ก ์ ์ง๋ฉ๋๋ค.
๋ชจ๋ ์ฌ์ฉ ์ฌ๋ก์ ์ ํฉํ๋๋ก ์๋ํ๋ ํฐ ๊ตฌ์กฐ์ฒด ํฌ๊ธฐ๋ฅผ ๊ฐ์ง ๋ฒ์ฉ ๊ฒฐํฉ๊ธฐ๊ฐ ์์ด์ผ ํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
ASP.NET Core๋ ํ์ฌ ์ํ๊ฐ 64๋นํธ์ธ ์์ฒด ํด์์ฝ๋ ๊ฒฐํฉ๊ธฐ ๋ฅผ ์ด๊ฒ์ผ๋ก ๊ต์ฒดํ ์ ์์ต๋๊น?
๋ชจ๋ int ํฌ๊ธฐ(FnvHashCode ๋ฑ)์ธ ๋ณ๋์ ํด์ ์ฝ๋ ์ ํ์ ๊ตฌ์ํ๊ณ ์์์ต๋๋ค.
์ด๊ฒ์ด ๊ฒฐํฉ ํญ๋ฐ๋ก ์ด์ด์ง์ง ์์ต๋๊น? ์ด API ๋์์ธ์ด ๋ฌด์์ผ๋ก ์ด์ด์ง๋์ง ๋ช ํํ ํ๊ธฐ ์ํด API ์ ์์ ์ผ๋ถ์ฌ์ผ ํฉ๋๋ค.
@jkotas ํ ๋ก ์ด๋ฐ์ ๋น์ทํ ๋ฐ๋ ์๊ฒฌ์ ๋ฐํ์ต๋๋ค. ํด์ ํจ์๋ฅผ ๋ค๋ฃจ๋ ค๋ฉด ์ฃผ์ ์ง์์ด ํ์ํฉ๋๋ค. ๊ทธ๋ฌ๋ 2001๋ ์ ํ๋ ์์ํฌ์ ๊ฐ์ฅ ๋ฟ๋ฆฌ์ ํด์ ์ฝ๋๋ฅผ ๋์ ํ์ฌ ๋ฐ์ํ ๋ฌธ์ ๋ฅผ ์์ ํ๋ ๊ฒ์ ์ดํดํ๊ณ ์ง์งํ๋ฉฐ ํด์๋ฅผ ๊ฒฐํฉํ๋ ๋ฐฉ๋ฒ์ ์ฒ๋ฐฉํ์ง ์์ต๋๋ค. ์ด ์ค๊ณ๋ 99%์ ๊ฒฝ์ฐ(ํด์์ ํต๊ณ์ ์์ฑ์ด ์ถฉ๋ถํ๊ธฐ ๋๋ฌธ์ ์ฃผ์ ์ง์์ ์ฌ์ฉํ ์ ์๊ฑฐ๋ ํ์ํ ๊ฒฝ์ฐ)์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฒ์ ๋ชฉํ๋ก ํฉ๋๋ค. ASP.Net Core๋ https://github.com/dotnet/corefx/issues/13757 ์์ ๋ ผ์๋ฅผ ์ํด ์ ์๋ ๊ฒ๊ณผ ๊ฐ์ ๋น์์คํ ์ด์ ๋ธ๋ฆฌ์ ๋ฒ์ฉ ํ๋ ์์ํฌ์ ์ด๋ฌํ ๊ฒฐํฉ๊ธฐ๋ฅผ ์ฌ์ฉํ ์ ์์ด์ผ ํฉ๋๋ค.
99%์ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๊ธฐ ์ฌ์ด ํด์์ฝ๋ ๊ฒฐํฉ๊ธฐ๋ฅผ ๊ฐ๋ ๊ฒ์ด ์ข๋ค๋ ๋ฐ ๋์ํฉ๋๋ค. ๊ทธ๋ฌ๋ 32๋นํธ๋ณด๋ค ๋ ๋ง์ ๋ด๋ถ ์ํ๋ฅผ ํ์ฉํด์ผ ํฉ๋๋ค.
BTW: ASP.NET์ ์๋ ํด์์ฝ๋ ๊ฒฐํฉ์ ์ ์ฐฝํ ํจํด์ ์ฌ์ฉํ์ง๋ง ๋ฒ๊ทธ๋ฅผ ๋์น๊ธฐ ์ฝ๊ธฐ ๋๋ฌธ์ ์ค๋จํ์ต๋๋ค. https://github.com/aspnet/Razor/pull/537
ํด์ ํ๋ฌ๋ฉ ๋ณด์์ ๊ดํ @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
๊ฐ ๋ณ๊ฒฝ ๊ฐ๋ฅํด์ผ ํ๋ค๊ณ ๋งํ๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค. ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๊ตฌ์กฐ์ฒด๋ ๋ฌธ์ ์ธก๋ฉด์์ ํจ์ฌ ๋ ๋์ฉ๋๋ค. ๊ตฌ์กฐ์ฒด๋ฅผ ๋ถ๋ณ์ผ๋ก ์ ์งํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํด์ ํ๋ฌ๋ฉ ๋ณด์์ ๋ํด.
์ฌ๊ธฐ์๋ ๋ ๊ฐ์ง ์ธก๋ฉด์ด ์์ต๋๋ค. ์ฌ๋ฐ๋ฅธ ๊ตฌ์ฑ ์ค๊ณ(๊ฐ๋ ฅํ ๋ฐ์ดํฐ ๊ตฌ์กฐ ๋ฑ); ๋ฐ ๊ธฐ์กด ์ค๊ณ์ ๋ฌธ์ ์ํ. ๋ ๋ค ์ค์ํฉ๋๋ค.
@karelz ๋งค๊ฐ๋ณ์ ์ด๋ฆ ์ง์ ๊ด๋ จ
๋๋ ๋น์ ์ด ์๋์ผ๋ก/์ค์๋ก ๋น์ ์ ์ ์ dotnet/corefx#8034(comment)์์ arg name obj๋ฅผ ๊ฐ์ผ๋ก ๋ณ๊ฒฝํ๋ค๋ ๊ฒ์ ์์์ฐจ๋ ธ์ต๋๋ค. IMO๊ฐ ์ป๋ ๊ฒ์ ๋ ์ ์บก์ฒํ๋ obj๋ก ๋ค์ ์ ํํ์ต๋๋ค. ์ด ์ปจํ ์คํธ์์ ์ด๋ฆ ๊ฐ์ "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๋นํธ์ธ ์์ฒด ํด์์ฝ๋ ๊ฒฐํฉ๊ธฐ๋ฅผ ์ด๊ฒ์ผ๋ก ๊ต์ฒดํ ์ ์์ต๋๊น?
์ ์ ์ผ๋ก; ๋์ผํ ํด์ฑ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํฉ๋๋ค. ๋ฐฉ๊ธ ์ด ํ ์คํธ ์ฑ ์ ๋ง๋ค์ด ์ถฉ๋ ํ์๋ฅผ ์ธก์ ํ๊ณ 10๋ฒ ์คํํ์ต๋๋ค. 64๋นํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ํฐ ์ฐจ์ด๋ ์์ต๋๋ค.
๋ชจ๋ int ํฌ๊ธฐ(FnvHashCode ๋ฑ)์ธ ๋ณ๋์ ํด์ ์ฝ๋ ์ ํ์ ๊ตฌ์ํ๊ณ ์์์ต๋๋ค.
์ด๊ฒ์ด ๊ฒฐํฉ ํญ๋ฐ๋ก ์ด์ด์ง์ง ์์ต๋๊น? ์ด API ๋์์ธ์ด ๋ฌด์์ผ๋ก ์ด์ด์ง๋์ง ๋ช ํํ ํ๊ธฐ ์ํด API ์ ์์ ์ผ๋ถ์ฌ์ผ ํฉ๋๋ค.
@jkotas , ๊ทธ๋ ์ง ์์ต๋๋ค. ์ด ํด๋์ค์ ๋์์ธ์ ๋ฏธ๋์ ํด์ฑ API์ ๋ํ ๋์์ธ์ ํ์ ์ ์ผ๋ก ์ค์ ํ์ง ์์ต๋๋ค. ์ด๋ ๋ ๊ณ ๊ธ ์๋๋ฆฌ์ค๋ก ๊ฐ์ฃผ๋์ด์ผ ํ๋ฉฐ dotnet/corefx#13757๊ณผ ๊ฐ์ ๋ค๋ฅธ ์ ์์ผ๋ก ์ด๋ํด์ผ ํ๋ฉฐ ๋ค๋ฅธ ์ค๊ณ ๋
ผ์๊ฐ ์์ ๊ฒ์
๋๋ค. GetHashCode
์ฌ์ ์์ ์ด๋ ค์์ ๊ฒช๊ณ ์๋ ์ด๋ณด์๋ฅผ ์ํด ์ผ๋ฐ ํด์ฑ ์๊ณ ๋ฆฌ์ฆ์ ์ํ ๊ฐ๋จํ API๋ฅผ ๊ฐ๋ ๊ฒ์ด ํจ์ฌ ๋ ์ค์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
99%์ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๊ธฐ ์ฌ์ด ํด์์ฝ๋ ๊ฒฐํฉ๊ธฐ๋ฅผ ๊ฐ๋ ๊ฒ์ด ์ข๋ค๋ ๋ฐ ๋์ํฉ๋๋ค. ๊ทธ๋ฌ๋ 32๋นํธ๋ณด๋ค ๋ ๋ง์ ๋ด๋ถ ์ํ๋ฅผ ํ์ฉํด์ผ ํฉ๋๋ค.
32๋นํธ๋ณด๋ค ๋ ๋ง์ ๋ด๋ถ ์ํ๊ฐ ํ์ํ ๊ฒฝ์ฐ๋ ์ธ์ ์ ๋๊น? ํธ์ง: ์ฌ๋๋ค์ด ์ฌ์ฉ์ ์ ์ ํด์ฑ ๋ ผ๋ฆฌ๋ฅผ ํ๋ฌ๊ทธ์ธํ ์ ์๋๋ก ํ๋ ค๋ฉด ๊ณ ๊ธ ์๋๋ฆฌ์ค๋ก ๊ฐ์ฃผ๋์ด์ผ ํ๊ณ dotnet/corefx#13757์์ ๋ ผ์ํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํ์ฌ ๊ฐ ๋๋ฉ์ธ์์ ๋ณ๊ฒฝ๋๋ Marvin32๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
๋ง์ต๋๋ค. ๋ฌธ์์ด ํด์์ฝ๋ ๋ฌด์์ํ ์ํ๋ .NET Core์์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฑํ๋์ด ์์ต๋๋ค. ํธํ์ฑ ๋๋ฌธ์ ์ ์ฒด .NET Framework์ ๋ ๋ฆฝ ์คํํ ์ฑ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฑํ๋์ด ์์ง ์์ต๋๋ค. ์ด๋ ๋จ์ ์ ํตํด์๋ง ํ์ฑํ๋ฉ๋๋ค(์: ๊ณ ์ํ ํ๊ฒฝ).
.NET Core์ ๋น๋ฌด์์ ํด์ฑ์ ์ํ ์ฝ๋๊ฐ ์ฌ์ ํ ์์ง๋ง ์ญ์ ํด๋ ๊ด์ฐฎ์ต๋๋ค. ๋๋ ์ฐ๋ฆฌ๊ฐ ๊ทธ๊ฒ์ ๋ค์ ํ์๋ก ํ ๊ฒ์ด๋ผ๊ณ ๊ธฐ๋ํ์ง ์์ต๋๋ค. ๋ํ ๋ ์ด์ ๋ฌด์์๊ฐ ์๋ ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ ์ง ์ฌ๋ถ๋ฅผ ํ์ธํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ฌธ์์ด ํด์์ฝ๋ ๊ณ์ฐ์ด ์กฐ๊ธ ๋ ๋นจ๋ผ์ง๋๋ค.
๋ฌด์์ ๋ฌธ์์ด ํด์์ฝ๋๋ฅผ ๊ณ์ฐํ๋ ๋ฐ ์ฌ์ฉ๋๋ Marvin32 ์๊ณ ๋ฆฌ์ฆ์ 64๋นํธ ๋ด๋ถ ์ํ๋ฅผ ๊ฐ์ต๋๋ค. MS ๊ณผ๋ชฉ ์ ๋ฌธ๊ฐ๋ค์ด ๋ฝ์์ต๋๋ค. ๋๋ ๊ทธ๋ค์ด 64๋นํธ ๋ด๋ถ ์ํ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ์ถฉ๋ถํ ์ด์ ๊ฐ ์๋ค๊ณ ํ์ ํ๋ฉฐ, ๋จ์ง ์ผ์ ๋๋ฆฌ๊ฒ ํ๊ธฐ ์ํด ์ฌ์ฉํ์ง ์์์ต๋๋ค.
๋ฒ์ฉ ํด์ ๊ฒฐํฉ๊ธฐ๋ ์ด ์ํ๋ฅผ ๊ณ์ ๋ฐ์ ์์ผ์ผ ํฉ๋๋ค. ๋ฌด์์ ์๋์ ์ถฉ๋ถํ ๊ฐ๋ ฅํ ํด์์ฝ๋ ๊ฒฐํฉ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ์ด์์ ์ผ๋ก๋ ๋ฌด์์ ๋ฌธ์์ด ํด์ฑ๊ณผ ๋์ผํ Marvin32๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋ฌด์์ ๋ฌธ์์ด ํด์์ฝ๋๋ฅผ ๊ณ์ฐํ๋ ๋ฐ ์ฌ์ฉ๋๋ Marvin32 ์๊ณ ๋ฆฌ์ฆ์ 64๋นํธ ๋ด๋ถ ์ํ๋ฅผ ๊ฐ์ต๋๋ค. MS ๊ณผ๋ชฉ ์ ๋ฌธ๊ฐ๋ค์ด ๋ฝ์์ต๋๋ค. ๋๋ ๊ทธ๋ค์ด 64๋นํธ ๋ด๋ถ ์ํ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ์ถฉ๋ถํ ์ด์ ๊ฐ ์๋ค๊ณ ํ์ ํ๋ฉฐ, ๋จ์ง ์ผ์ ๋๋ฆฌ๊ฒ ํ๊ธฐ ์ํด ์ฌ์ฉํ์ง ์์์ต๋๋ค.
@jkotas , ์ฐ๊ฒฐํ ํด์ ์ฝ๋ ๊ฒฐํฉ๊ธฐ๋ Marvin32๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค. ๊ทธ๊ฒ์ non-randomized string.GetHashCode
์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋์ผํ ์์งํ DJBx33x ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํฉ๋๋ค.
๋ฒ์ฉ ํด์ ๊ฒฐํฉ๊ธฐ๋ ์ด ์ํ๋ฅผ ๊ณ์ ๋ฐ์ ์์ผ์ผ ํฉ๋๋ค. ๋ฌด์์ ์๋์ ์ถฉ๋ถํ ๊ฐ๋ ฅํ ํด์์ฝ๋ ๊ฒฐํฉ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ์ด์์ ์ผ๋ก๋ ๋ฌด์์ ๋ฌธ์์ด ํด์ฑ๊ณผ ๋์ผํ Marvin32๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ด ์ ํ์ ํด์ DoS ๊ณต๊ฒฉ์ ์ทจ์ฝํ ์ฅ์์์ ์ฌ์ฉํ๊ธฐ ์ํ ๊ฒ์ด ์๋๋๋ค. ์ด๊ฒ์ ์ถ๊ฐ/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๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค).
์ด๊ฒ์ ์ถ๊ฐ/xor๋ฅผ ๋ ์ ๋ชจ๋ฅด๋ ์ฌ๋๋ค์ ๋์์ผ๋ก ํฉ๋๋ค.
์ด๊ฒ์ด ๋ฐ๋ก ๊ฒฌ๊ณ ํ ๊ฒ์ด ์ค์ํ ์ด์ ์ ๋๋ค. .NET์ ํต์ฌ ๊ฐ์น๋ ์ ๋ชจ๋ฅด๋ ์ฌ๋๋ค์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค๋ ๊ฒ์ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ๊ฐ ๊ทธ๊ฒ์ ์๋ ๋์ IntPtr
https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/IntPtr.cs#L119์ ๋ํด ์์ง ๋ง์ธ์.
bad
๊ฐ dab
์ ์ถฉ๋ํ๊ธฐ ๋๋ฌธ์ xor๋ ์๋ง๋ ์ต์
์ ๊ฒ์
๋๋ค.
์ํ๋
ValueTuple
ํด์ฑ ์๊ณ ๋ฆฌ์ฆ ๊ตฌํ
์ข์ ์ง์ . ValueTupup์ด ๋ฐฐ์ก๋์๋์ง ๋๋ ์์ง ์ด๋ฅผ ์ํํ ์๊ฐ์ธ์ง ํ์คํ์ง ์์ต๋๋ค. https://github.com/dotnet/corefx/issues/14046์ ์ด์์ต๋๋ค
IntPtr์ ์์ง ๋ง์
์ด๊ฒ์ ๊ณผ๊ฑฐ์ ์ค์์ ๋๋ค ... ์์ ์ ๊ธฐ์ค์ ํจ์ฌ ๋์ต๋๋ค.
@jkotas
์ด๊ฒ์ ๊ณผ๊ฑฐ์ ์ค์์ ๋๋ค ... ์์ ์ ๊ธฐ์ค์ ํจ์ฌ ๋์ต๋๋ค.
.Net Core์ ์์ ์ค ํ๋๋ ๊ทธ๋ฌํ "์์" ๋ณ๊ฒฝ์ ๋ํ ๊ธฐ์ค์ด ํจ์ฌ ๋ฎ์์ผ ํ๋ค๋ ๊ฒ์
๋๋ค. ๋๊ตฐ๊ฐ IntPtr.GetHashCode
๊ตฌํ์ ์์กดํ๋ ๊ฒฝ์ฐ(์ค์ ๋ก ํด์๋ ์ ๋จ) .Net Core ๋ฒ์ ์ ์
๊ทธ๋ ์ด๋ํ์ง ์๋๋ก ์ ํํ ์ ์์ต๋๋ค.
์ด์ ๊ฐ์ "์์" ๋ณ๊ฒฝ ์ฌํญ์ ๋ํ ๊ธฐ์ค์ ํจ์ฌ ๋ฎ์์ผ ํฉ๋๋ค.
์, ์ ์ฒด .NET Framework์ ๋น๊ต๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์์คํ
์ ํตํด ๋ณ๊ฒฝ ์ฌํญ์ ํธ์ํ๋ ค๋ฉด ์ฌ์ ํ ์์
์ ์ํํด์ผ ํ๋ฉฐ ๊ณ ํต๋ฐ์ ๊ฐ์น๊ฐ ์๋ค๋ ๊ฒ์ ์๊ฒ ๋ ์๋ ์์ต๋๋ค. ์ต๊ทผ์ ์๋ F#์ ๊นจ๋จ๋ฆฌ๊ธฐ ๋๋ฌธ์ ๋๋๋ ค์ง Tuple<T>
ํด์ฑ ์๊ณ ๋ฆฌ์ฆ์ ๋ณ๊ฒฝ์
๋๋ค. https://github.com/dotnet/coreclr/pull/6767#issuecomment -256896016
@jkotas
HashCode
64๋นํธ๋ฅผ ๋ง๋ ๋ค๋ฉด 32๋นํธ ํ๊ฒฝ์์ ๋ณ๊ฒฝํ ์ ์๋ ๋์์ธ์ด perf๋ฅผ ์ฃฝ์ผ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ญ๋๊น? ๋ค๋ฅธ ๋
์๋ค์ ์๊ฒฌ์ ๋์ํฉ๋๋ค. ๋น๋ ํจํด์ด ํจ์ฌ ๋ ๋์ ๊ฒ ๊ฐ์ต๋๋ค.
์ฑ๋ฅ์ ์ฃฝ์ฌ๋ผ - ์๋. ๊ตฌ๋ฌธ ์คํ์ ๋ํ ์ฑ๋ฅ ์ ํ - ์.
๊ตฌ๋ฌธ ์คํ์ ๋ํ ์ฑ๋ฅ ์ ํ - ์.
ํฅํ 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์ผ๋ก ์์ํ๋ ๊ฒ๊ณผ ๊ฐ์ด ๋ช
ํํ์ง ์์ ์์
์ ์ํํด์ผ ํฉ๋๊น? ์ฆ 0.CombineHash(this.FirstName).CombineHash(this.LastName)
.
์
๋ฐ์ดํธ: dotnet/corefx#14046 ์ ์ฃผ์ ์ ๋ฐ๋ผ ๊ธฐ์กด ํด์ ์์์ด ValueTuple
๋ํด ์ ์ง๋๊ธฐ๋ก ๊ฒฐ์ ๋์์ต๋๋ค.
@jamesqo ๋์์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
@jkotas ๋ฐ @VSadov ์์ ๋ง์ง๋ง ํ ๋ก ์์ ์ฐ๋ฆฌ๋ ๋ฌด์์ํ/์จ๋ฉ์ ์งํํ๋ ๊ฒ์ด ์ข์ง๋ง ๋ ๋น์ผ ํด์ ํจ์๋ฅผ ์ฑํํ๋ ๊ฒ์ ๋ณด๋ฅํ ๊ฒ์ ๋๋ค.
๋ฌด์์ํ๋ฅผ ์ํํ๋ฉด ํฅํ ํ์ํ ๊ฒฝ์ฐ ํด์ ํจ์๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
@jkotas , HashCode
๋ํ ํ์ฌ ROL 5 ๊ธฐ๋ฐ ํด์๋ฅผ ์ ์งํ๊ณ ๋ค์ 4๋ฐ์ดํธ๋ก ์ถ์ํ ์ ์์ต๋๊น? ์ด๊ฒ์ ๊ตฌ์กฐ์ฒด ๋ณต์ฌ์ ๋ชจ๋ ๋ฌธ์ ๋ฅผ ์ ๊ฑฐํฉ๋๋ค. HashCode.Empty
๊ฐ ์์์ ํด์ ๊ฐ์ ๋ํ๋ด๋๋ก ํ ์ ์์ต๋๋ค.
@svic
์, ์ด๊ฒ์ ๋ชจ๋ ์ ์์ ๋ํ ๋ฉ์๋๋ฅผ ์ค์ผ์ํค์ง๋ง ๋ถ๋ฆฌ๋ ์ด๋ฆ ๊ณต๊ฐ์ ๋ฐฐ์น๋ ์ ์์ผ๋ฉฐ ํด์๋ก ์์
ํ์ง ์์ผ๋ฉด ํฌํจํ์ง ์๊ณ ๋ณผ ์ ์์ต๋๋ค.
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 , HashCode์ ๋ํ ํ์ฌ ROL 5 ๊ธฐ๋ฐ ํด์๋ฅผ ์ ์งํ๊ณ ๋ค์ 4๋ฐ์ดํธ๋ก ์ถ์ํ ์ ์์ต๋๊น?
๊ณต๊ฐ ํ๋ซํผ ํด์์ฝ๋ ๊ตฌ์ถ ๋์ฐ๋ฏธ๊ฐ 64๋นํธ ์ํ๋ฅผ ์ฌ์ฉํด์ผ ๊ฒฌ๊ณ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. 32๋นํธ ์ ์ฉ์ธ ๊ฒฝ์ฐ ํนํ ๋ ๋ง์ ์์, ๋ฐฐ์ด ๋๋ ์ปฌ๋ ์ ์ ํด์ํ๋ ๋ฐ ์ฌ์ฉํ ๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํ๊ธฐ ์ฝ์ต๋๋ค. ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ ๊ฒฝ์ฐ์ ์ฌ์ฉํ์ง ์๋ ๊ฒฝ์ฐ์ ๋ํ ๋ฌธ์๋ ์ด๋ป๊ฒ ์์ฑํฉ๋๊น? ์, ๋นํธ๋ฅผ ํผํฉํ๋ ๋ฐ ์ฌ์ฉ๋๋ ์ถ๊ฐ ์ง์นจ์ด์ง๋ง ์ค์ํ์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ฌํ ์ข ๋ฅ์ ๋ช ๋ น์ ๋งค์ฐ ๋น ๋ฅด๊ฒ ์คํ๋ฉ๋๋ค. ๋ด ๊ฒฝํ์ ๋ฐ๋ฅด๋ฉด ๋๋ฌด ์ ์ ์์ ๋ฏน์ฑ์ ์ํํ๋ ๊ฒ์ด ๋๋ฌด ๋ง์ด ํ๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ ์ฌ๊ฐํ๊ธฐ ๋๋ฌธ์ ์ ์ ์๋ณด๋ค ๋ง์ ์์ ๋ฏน์ฑ์ ์ํํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋ํ ์ ์๋ API์ ํํ์ ๋ํด ์ฌ์ ํ ์ฐ๋ คํ๊ณ ์์ต๋๋ค. ๋ฌธ์ ๋ ํด์ ์ฝ๋ ๊ฒฐํฉ์ด ์๋๋ผ ํด์ ์ฝ๋ ๊ตฌ์ถ์ผ๋ก ์๊ฐํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ฅผ ํ๋ซํผ API๋ก ์ถ๊ฐํ๋ ๊ฒ์ ์๊ธฐ์์กฐ์ผ ์ ์์ผ๋ฉฐ, ์ด์ ๋ํด ๋ ๋์ ํจํด์ด ๋ํ๋ ์ง ์ง์ผ๋ด์ผ ํฉ๋๋ค. ์ด๊ฒ์ ๋๊ตฐ๊ฐ๊ฐ ์ด API๋ก (์์ค) nuget ํจํค์ง๋ฅผ ๊ฒ์ํ๊ฑฐ๋ corefx๊ฐ ์ด๋ฅผ ๋ด๋ถ ๋์ฐ๋ฏธ๋ก ์ฌ์ฉํ๋ ๊ฒ์ ๋ฐฉ์งํ์ง ์์ต๋๋ค.
64๋นํธ ์ํ๋ฅผ ๊ฐ์ง @jkotas ๋ ์ถ๋ ฅ์ด ์ ์ ํ ํต๊ณ์ ์์ฑ์ ๊ฐ์ง ๊ฒ์ด๋ผ๊ณ ๋ณด์ฅํ์ง ์์ต๋๋ค. ๊ฒฐํฉ ๊ธฐ๋ฅ ์์ฒด๋ ๋ด๋ถ 64๋นํธ ์ํ๋ฅผ ์ฌ์ฉํ๋๋ก ์ค๊ณ๋์ด์ผ ํฉ๋๋ค. ๋ํ ๊ฒฐํฉ ๊ธฐ๋ฅ์ด ์ข๋ค๋ฉด(ํต๊ณ์ ์ผ๋ก) ๋ ์๋ ๊ฒ ์ด์์ ์์ต๋๋ค. ํด์ฑ์ ๋ฌด์์ํ, ๋์ฌํ ๋ฐ ๊ธฐํ ๊ด์ฌ ์๋ ํต๊ณ์ ์์ฑ์ด ์๋ ๊ฒฝ์ฐ ๊ธฐ์ ์ ์ผ๋ก ํน์ํ๊ฒ ์กฐ์๋ ํด์ ๊ธฐ๋ฅ์ ๋งํ๋ฏ๋ก ํผํฉ์ด ์ค๋ช ๋ฉ๋๋ค.
์ข์ ํด์ ํจ์๊ฐ ๋ฌด์์ธ์ง ํ์ธํ์ญ์์ค(์ผ๋ถ๋ xor
๊ฐ์ต๋๋ค. http://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and -์๋ ๋ฐ https://research.neustar.biz/2012/02/02/choosing-a-good-hash-function-part-3/
@jamesqo BTW, "์๋๊ฐ ๋งค๋ฒ ๋ณ๊ฒฝ๋๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก ํด์(๋ฐํ์ ํด์๊ฐ ์๋)๋ฅผ ๊ฒฐํฉํ๊ณ ์์ต๋๋ค."์ ๊ฒฝ์ฐ ๊ฒฐํฉ๊ธฐ๊ฐ ์๋ํ์ง ์๋๋ค๋ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค. ... ์๋๊ฐ ์๋ ๊ณต๊ฐ ์์ฑ์?
@jkotas
๊ณต๊ฐ ํ๋ซํผ ํด์์ฝ๋ ๊ตฌ์ถ ๋์ฐ๋ฏธ๊ฐ 64๋นํธ ์ํ๋ฅผ ์ฌ์ฉํด์ผ ๊ฒฌ๊ณ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. 32๋นํธ ์ ์ฉ์ธ ๊ฒฝ์ฐ ํนํ ๋ ๋ง์ ์์, ๋ฐฐ์ด ๋๋ ์ปฌ๋ ์ ์ ํด์ํ๋ ๋ฐ ์ฌ์ฉํ ๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํ๊ธฐ ์ฝ์ต๋๋ค.
์ด๊ฒ์ด ๊ฒฐ๊ตญ ๋จ์ผ int
๋ก ์์ถ๋๋ ์์ ์ด ์ค์ํฉ๋๊น?
@jamesqo ์ค์ ๋ก๋ ์ํ ํฌ๊ธฐ๊ฐ ๊ฒฌ๊ณ ์ฑ์ด ์๋๋ผ ๊ธฐ๋ฅ์๋ง ์์กดํฉ๋๋ค. ์ฌ์ค ๊ฒฐํฉ์ด ๊ทธ๋ฐ ์์ผ๋ก ์๋ํ๋๋ก ์ค๊ณ๋์ง ์์๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก ํด์ ํจ์๋ฅผ ๋ ์ ํ์ํฌ ์ ์์ผ๋ฉฐ ๊ฐ์ ๋ก ์์์ฑ์ ์ป์ ์ ์๊ธฐ ๋๋ฌธ์ ๊ธฐ๊ปํด์ผ ๋ฆฌ์์ค๋ฅผ ๋ญ๋นํ๊ณ ์์ต๋๋ค.
๊ฒฐ๋ก : ํจ์๊ฐ ํต๊ณ์ ์ผ๋ก ์ฐ์ํ๊ฑฐ๋ ๋ ๋๋น ์ง ๊ฒ์ด ๊ฑฐ์ ๋ณด์ฅ๋๋ค๋ ์ ์ ์ถ๊ฐ๋ก ํ์ธํ๋ ๊ฒ์ ๋๋ค.
์ด๋ ํญ๋ชฉ ๊ฐ์ ์๊ด ๊ด๊ณ๊ฐ ์๋์ง ์ฌ๋ถ์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. ์๊ด ๊ด๊ณ๊ฐ ์์ผ๋ฉด 32๋นํธ ์ํ์ ๋จ์ rotl(๋๋ xor)์ด ์ ์๋ํฉ๋๋ค. ์๊ด ๊ด๊ณ๊ฐ ์์ผ๋ฉด ์์กดํฉ๋๋ค.
๋๊ตฐ๊ฐ๊ฐ ๊ฐ๋ณ ๋ฌธ์์์ ๋ฌธ์์ด ํด์ ์ฝ๋๋ฅผ ๋น๋ํ๋ ๋ฐ ์ด๊ฒ์ ์ฌ์ฉํ๋์ง ๊ณ ๋ คํ์ญ์์ค. ๋๊ตฐ๊ฐ๊ฐ ์ค์ ๋ก ๋ฌธ์์ด์ ๋ํด ์ด ์์ ์ ์ํํ ๊ฐ๋ฅ์ฑ์ ์์ง๋ง ๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ค๋๋ค.
for (int i = 0; i < str.Length; i++)
hashCodeBuilder.Add(str[i]);
์ค์ ๋ฌธ์์ด์ ๋ฌธ์๋ ์๊ด ๊ด๊ณ๊ฐ ์๋ ๊ฒฝํฅ์ด ์๊ธฐ ๋๋ฌธ์ 32๋นํธ ์ํ ๋ฐ ๋จ์ rotl ๋ฌธ์์ด์ ๋ํด ์ข์ง ์์ ๊ฒฐ๊ณผ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๊ฒ์ด ์ฌ์ฉ๋๋ ํญ๋ชฉ์ ์ผ๋ง๋ ์์ฃผ ์๊ด ๊ด๊ณ๊ฐ ์์ผ๋ฉฐ ์ผ๋ง๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ์ค๊น์? ๋งํ๊ธฐ๋ ์ด๋ ต์ง๋ง ์ค์ํ์ ๊ฒ๋ค์ ์์์น ๋ชปํ ๋ฐฉ์์ผ๋ก ์๊ด๋๋ ๊ฒฝํฅ์ด ์์ต๋๋ค.
API ์ง์ Hash randomization์ ๋ค์ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ฉด ์ข์ ๊ฒ์ ๋๋ค.
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://github.com/dotnet/corefx/issues/8034#issuecomment -261301533
๋๋ ์ด๊ฒ์ด ๋น-์ํธํ ํด์ฑ ํจ์๊ฐ ์๋๋ผ ์๊ด๋์ง ์์ ํด์ ์ฝ๋๋ฅผ ๊ฒฐํฉํ๋ ๋น ๋ฅธ ๋ฐฉ๋ฒ์ด๋ผ๋ ๋์์ธ์ ํ ๋ฒ ์ ํธํฉ๋๋ค.
์๊ด๋์ง ์์ ํด์ ์ฝ๋๋ฅผ ๊ฒฐํฉํ๋ ๊ฐ์ฅ ๋น ๋ฅธ ๋ฐฉ๋ฒ์ xor...
์ฌ์ค์ด์ง๋ง ์ง๋ ๋ฒ์๋ ์ ์๋ํ์ง ์์๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค(IntPtr์ด ์๊ฐ๋ฉ๋๋ค). Rotation ๋ฐ XOR(ํ์ฌ)๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๋น ๋ฅด๋ฉฐ ๋๊ตฐ๊ฐ๊ฐ ์ผ์ข ์ ๊ด๋ จ ํญ๋ชฉ์ ๋ฃ์ด๋ ์์ค์ด ์์ต๋๋ค.
public static HashCode CreateRandomized(Type type);
๋๋ public static HashCode CreateRandomized<T>();
๋ฐฉ๋ฒ ๋๋ ๋ ๋ค๋ฅผ ์ฌ์ฉํ์ฌ ํด์ ์ฝ๋ ๋ฌด์์ํ๋ฅผ ์ถ๊ฐํฉ๋๋ค.
@jkotas ๋ ๋์ ํจํด์ ์ฐพ์ ๊ฒ ๊ฐ์ต๋๋ค. C# 7 ref ๋ฐํ์ ์ฌ์ฉํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ๋งค๋ฒ 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
๋ ์์ง ์๋ํ์ง ์์ง๋ง ์ฌ๊ธฐ ์์ ํ์ฑํํ๊ธฐ ์ํด Roslyn์์ PR์ ๋ด
๋๋ค
@AlexRadch ์ ํ์ ํด์ ์ฝ๋๋ฅผ ์ป๋ ๋ฐ ๋น์ฉ์ด ๋ง์ด ๋ค๊ธฐ ๋๋ฌธ์ ํด์๋ฅผ ์ ํ๊ณผ ๋ ๊ฒฐํฉํ๋ ๊ฒ์ด ํ๋ช ํ์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
@jamesqo public static HashCode CreateRandomized<T>();
์ ํ ํด์ ์ฝ๋๋ฅผ ๊ฐ์ ธ์ค์ง ์์ต๋๋ค. ์ด ์ ํ์ ๋ํด ์์์ HashCode๋ฅผ ์์ฑํฉ๋๋ค.
@jamesqo " ref this
์ด(๊ฐ) ์์ง ์๋ํ์ง ์์ต๋๋ค". ๋ก์ฌ๋ฆฐ์ ๋ฌธ์ ๊ฐ ํด๊ฒฐ ๋๋๋ผ๋ ์ผ๋จ ref this
์ ์ ๋์ corefx์ REPO (๋๋ ํ์คํ ์ผ๋ง๋ ์ค๋, @stephentoub ์๋ง ์ค์ ํ ์ ์์ต๋๋ค ๊ธฐ๋ํ์ง ์์์)์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋์์ธ ๋
ผ์๋ ์ฌ๊ธฐ์ ์๋ ด๋์ง ์์ต๋๋ค. ๊ฒ๋ค๊ฐ 200๊ฐ์ ๋๊ธ์ ๋ฐ๋ผ๊ฐ๊ธฐ ๋งค์ฐ ์ด๋ ต์ต๋๋ค.
์ฐ๋ฆฌ๋ ๋ค์ ์ฃผ์ @jkotas ๋ฅผ ์ก๊ณ ๋ค์ ํ์์ผ์ API ๊ฒํ ์์ ์ ์์ ํ๋ฌ์ํ ๊ณํ์
๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ถ๊ฐ ์๊ฒฌ์ ์ํด ์ ์์๋ฅผ ์ฌ๊ธฐ์ ๋ค์ ๊ฒ์ํ ๊ฒ์
๋๋ค.
์์์: ๋๋ ๊ธด ํ ๋ก ์ ๋ฐ๋ฅด๋ ๋ถ๋ด์ ์ค์ด๊ธฐ ์ํด ๋ค์ ์ฃผ์ ์ฐ๋ฆฌ๊ฐ ๊ทธ๊ฒ์ ๊ฐ์ง ๋ ์ด ๋ฌธ์ ๋ฅผ ๋ซ๊ณ "์ถ๋ณต๋ฐ์ ์ ์"์ผ๋ก ์ ๋ฌธ์ ๋ฅผ ๋ง๋ค ๊ฒ์ ์ ์ํฉ๋๋ค. ๋์ ์๊ฐ์ด๋ผ๊ณ ์๊ฐ๋๋ฉด ์๋ ค์ฃผ์ญ์์ค.
@jcouv ์์ง ์๋ํ์ง ์๋ ๊ฒ์ ๊ด์ฐฎ์ต๋๋ค. ์ด ๋์์ธ์ด ์ถ์๋ ๋ ๋ฐ๋ผ๊ฐ Unsafe
์ฌ์ฉํ์ฌ ์ผ์์ ์ผ๋ก ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.)
@karelz OK :smile: ๋์ค์ ์๊ฐ์ด ๋๋ฉด ์ด ์ ์์ ๋ซ๊ณ ์ ์ ์์ ์ด๊ฒ ์ต๋๋ค. ๋๋ ๋์ํ๋ค; ๋ด ๋ธ๋ผ์ฐ์ ๋ 200๊ฐ ์ด์์ ๋๊ธ์ ์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
@karelz ๋๋ ๊ฑธ๋ฆผ๋์ ์ณค๋ค; ๋ฌธ์ ์ PR์ด ๊ฐ ์ ํ์ด ์๋ ์ฐธ์กฐ ์ ํ์ ๋ํด ref this
๋ฐํ์ ํ์ฑํํ๋ ค๊ณ ์๋ํ ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค. ref this
๋ ๊ตฌ์กฐ์ฒด์์ ์์ ํ๊ฒ ๋ฐํ๋ ์ ์์ต๋๋ค. ์ด์ ๋ ์ฌ๊ธฐ ๋ฅผ ์ฐธ์กฐ
์ด์จ๋ ์ด ๋ฌธ์ ๋ ๋ซ๊ฒ ์ต๋๋ค. ์ฌ๊ธฐ์์ ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ์ด์์ต๋๋ค. https://github.com/dotnet/corefx/issues/14354
C#vNext๋ผ๊ณ ๊ฐ์ ํ์ง๋ง ๊ฐ ์ ํ ํ์ฅ ๋ฉ์๋ ๊ฒ์๋ฌผ https://github.com/dotnet/roslyn/pull/15650 ์์ ref "this"๋ฅผ ๋ฐํํ ์ ์์ด์ผ ํฉ๋๋ค.
@benaadams
C#vNext๋ผ๊ณ ๊ฐ์ ํ์ง๋ง dotnet/roslyn#15650 ์ดํ์ ๊ฐ ์ ํ ํ์ฅ ๋ฉ์๋์์ ref "this"๋ฅผ ๋ฐํํ ์ ์์ด์ผ ํฉ๋๋ค.
์ณ์. ref this
ํ์ฅ ๋ฉ์๋์์ this
๋ฅผ ๋ฐํํ๋ ๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ผ๋ฐ ๊ตฌ์กฐ์ฒด ์ธ์คํด์ค ๋ฉ์๋์์ this
๋ฅผ ๋ฐํํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค. ์ ๊ทธ๋ฐ์ง์ ๋ํ ํผํฌ์ฑ์ด์ ํ์ ์ธ๋ถ ์ฌํญ์ด ๋ง์ด ์์ต๋๋ค :(
@redknightlois
์ฐ๋ฆฌ๊ฐ ์๊ฒฉํ๊ฒ ํ๊ณ ์ถ๋ค๋ฉด ์ ์ผํ ํด์๋
uint
์ด์ด์ผ ํฉ๋๋ค. ํ๋ ์์ํฌ๊ฐ ํด๋น ์กฐ๋ช ์๋์์int
๋ฐํํ๋ ๊ฒ์ ๊ฐ๊ณผ๋ก ๋ณผ ์ ์์ต๋๋ค.
CLS ์ค์? ๋ถํธ ์๋ ์ ์๋ CLS ๊ท๊ฒฉ์ด ์๋๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์ ์ @KrzysztofCwalina ๋ ์ฌ์ฉํ ๊ทผ๊ฑฐ์์ต๋๋ค. ํ๋งค ๋!