.NETãªããžã§ã¯ãã¢ãã«ã§ã¯ãä»ã®å€ãã®ãœãããŠã§ã¢ãã©ãããã©ãŒã ãšåæ§ã«ãåç
§ããã³å€ã«ãã£ãŠãªããžã§ã¯ããæ¯èŒã§ããããšã¯ããç¥ãããŠããŸãã
ããã©ã«ãã§ã¯ã察å¿ããå€æ°ã«åãåç
§ãå«ãŸããŠããå Žåã2ã€ã®ãªããžã§ã¯ãã¯çãããšèŠãªãããŸãã ãã以å€ã®å Žåããªããžã§ã¯ãã¯çãããªããšèŠãªãããŸãã
ãã ããç¹å®ã®ã¯ã©ã¹ã®ãªããžã§ã¯ãã®å
容ãç¹å®ã®æ¹æ³ã§äžèŽããŠããå Žåããããã®ãªããžã§ã¯ããåçãšèŠãªãå¿
èŠãããå ŽåããããŸãã
å人ããŒã¿ãå«ãPersonã¯ã©ã¹ããããšããŸã-å人ã®ååãå§ãç幎ææ¥ã
ãã®ã¯ã©ã¹ãäŸãšããŠäœ¿çšããŠã以äžãæ€èšããŠãã ããã
- ãã®ã¯ã©ã¹ã®ãªããžã§ã¯ããæšæºã®.NETã€ã³ãã©ã¹ãã©ã¯ãã£ã䜿çšããŠå€ã§æ¯èŒãããããã«ãã¯ã©ã¹ã«æå°éå¿
èŠãªæ¹åã»ããã
- ãã®ã¯ã©ã¹ã®ãªããžã§ã¯ããåžžã«æšæºã®.NETã€ã³ãã©ã¹ãã©ã¯ãã£ã䜿çšããŠå€ã§æ¯èŒãããããã«ããããã®æå°éã®å¿
èŠãã€ååãªæ¹åã»ãã-æ¯èŒãåç
§ã«ãã£ãŠè¡ãããã¹ãã§ããããšãæ確ã«ç€ºãããŠããªãéã
ã±ãŒã¹ããšã«ãå¯èœãªéãäžè²«æ§ã®ããã³ã³ãã¯ããªã³ããŒïŒããŒã¹ãã®ãªãçç£çãªã³ãŒããåŸãããããã«ãå€ã«ãããªããžã§ã¯ãã®æ¯èŒãå®è£
ããæ¹ãè¯ãæ¹æ³ãæ€èšããŸãã
ãã®ã¿ã¹ã¯ã¯ãäžèŠãããšããã»ã©ç°¡åã§ã¯ãããŸããã
ãŸãããã®ã¿ã¹ã¯ã®å®è£
ãç°¡çŽ åããããã«ããã©ãããã©ãŒã ã«ã©ã®ãããªæ¹åãå ããããšãã§ããããæ€èšããŠãã ããã
人ç©ã¯ã©ã¹ïŒ
ã¯ã©ã¹Personusing System; namespace HelloEquatable { public class Person { protected static string NormalizeName(string name) => name?.Trim() ?? string.Empty; protected static DateTime? NormalizeDate(DateTime? date) => date?.Date; public string FirstName { get; } public string LastName { get; } public DateTime? BirthDate { get; } public Person(string firstName, string lastName, DateTime? birthDate) { this.FirstName = NormalizeName(firstName); this.LastName = NormalizeName(lastName); this.BirthDate = NormalizeDate(birthDate); } } }
Personã¯ã©ã¹ã®2ã€ã®ãªããžã§ã¯ããäœããã®æ¹æ³ã§æ¯èŒãããå ŽåïŒ
ãªããžã§ã¯ããæãå€æ°ã«åããªã³ã¯ãå«ãŸããŠããå Žåã«ã®ã¿ããªããžã§ã¯ãã¯çãããšèŠãªãããŸãã
ããã·ã¥ã»ããïŒããã·ã¥ãããïŒããã³
èŸæžã«é
眮ãããå Žåããªããžã§ã¯ãã¯ãªã³ã¯ãäžèŽããå Žåã«ã®ã¿çãããšèŠãªãããŸãã
ã¯ã©ã€ã¢ã³ãã³ãŒãã®å€ã§ãªããžã§ã¯ããæ¯èŒããã«ã¯ã次ã®åœ¢åŒã®è¡ãèšè¿°ããå¿
èŠããããŸãã
ã³ãŒã var p1 = new Person("John", "Smith", new DateTime(1990, 1, 1)); var p2 = new Person("John", "Smith", new DateTime(1990, 1, 1)); bool isSamePerson = p1.BirthDate == p2.BirthDate && p1.FirstName == p2.FirstName && p1.LastName == p2.LastName;
泚ïŒ
- Personã¯ã©ã¹ã¯ãFirstNameãšLastNameã®æååããããã£ãåžžã«nullã§ã¯ãªãããã«å®è£
ãããŸã ã
FirstNameãŸãã¯LastNameãäžæïŒèšå®ãããŠããªãïŒã®å Žåã 空ã®æååãå€ããªãããšã®å
åãšããŠé©ããŠããŸãã
ããã«ãããFirstNameãã£ãŒã«ããšLastNameãã£ãŒã«ãã®ããããã£ãšã¡ãœãããåç
§ãããšãã«NullReferenceExceptionãåé¿ãããŸãããŸãã nullãšç©ºã®æååãæ¯èŒãããšãã«è¡çªãåé¿ãããŸãã - ããã©ããããBirthDateããããã£ã¯NullableïŒOf TïŒæ§é ãšããŠå®è£
ãããŸãã ç幎ææ¥ãäžæïŒèšå®ãããŠããªãïŒã®å Žåã¯ãããããã£ã«01/01 / 1900ã01 / 01 / 1970ã01 / 01/0001ãŸãã¯MinValueã®åœ¢åŒã®ç¹å¥ãªå€ã§ã¯ãªããæ£ç¢ºã«äžå®ã®å€ãæ ŒçŽããããšããå§ãããŸãã
- ãªããžã§ã¯ããå€ã§æ¯èŒããå Žåãæåã¯æ¥ä»ã®æ¯èŒã§ãã äžè¬çãªå Žåã®ããŒã¿åå€æ°ã®æ¯èŒã¯ãæååã®æ¯èŒãããé«éã§ãã
- æ¥ä»ãšæååã®æ¯èŒã¯ãçå€æŒç®åã䜿çšããŠå®è£
ãããŸãã ç䟡æŒç®åã¯å€ã«ãã£ãŠæ§é ãæ¯èŒããæååã®å Žåãç䟡æŒç®åã¯ãªãŒããŒããŒããããåæ§ã«å€ã«ãã£ãŠæååãæ¯èŒããŸãã
Personã¯ã©ã¹ã®ãªããžã§ã¯ãã次ã®æ¹æ³ã§å€ã§æ¯èŒããã«ã¯ïŒ
Personã¯ã©ã¹ã®å Žåã次ã®
ããã« Object.EqualsïŒObjectïŒããã³
Object.GetHashCodeïŒïŒã¡ãœããã
ãªãŒããŒã©ã€ãããå¿
èŠããã
ãŸã ã
- EqualsïŒObjectïŒã¡ãœããã¯ãå€ã®çµã¿åããããªããžã§ã¯ãã®å€ã圢æããã¯ã©ã¹ã®ãã£ãŒã«ããæ¯èŒããŸãã
- GetHashCodeïŒïŒã¡ãœããã¯ãçãããªããžã§ã¯ãïŒã€ãŸãã EqualsïŒObjectïŒã䜿çšããæ¯èŒãtrueãè¿ããªããžã§ã¯ãïŒã«å¯ŸããŠåãããã·ã¥ã³ãŒããè¿ãå¿
èŠããããŸã ã
ãªããžã§ã¯ãã®ããã·ã¥ã³ãŒããç°ãªãå Žåããªããžã§ã¯ãã¯çãããããŸããã çãããªããªããžã§ã¯ãã¯åãããã·ã¥ã³ãŒããæã€ããšãã§ããŸãã
ïŒããã·ã¥ã³ãŒããååŸããã«ã¯ãå€ã§ãªããžã§ã¯ããæ¯èŒããããã«Equalsã§äœ¿çšããããã£ãŒã«ãã®GetHashCodeïŒïŒå€ã®ãæä»ç OR ãæäœã®çµæãé垞䜿çšãããŸãã
ããããã®ãã£ãŒã«ãããã®ãã£ãŒã«ãã®ããã·ã¥ã³ãŒãã§ã¯ãªã32ãããæŽæ°ã®å Žåããã£ãŒã«ãå€èªäœã䜿çšã§ããŸãã
2ã€ã®çãããªããªããžã§ã¯ããåãããã·ã¥ã³ãŒããæã€å Žåãè¡çªã®å¯èœæ§ãæå°éã«æããããã«ãããŸããŸãªæé©åãå¯èœã§ãã
EqualsïŒObjectïŒã¡ãœããã®
ããã¥ã¡ã³ãã«ã¯ç¹å¥ãªèŠä»¶ãå«ãŸããŠãããšããäºå®ã«ç¹ã«æ³šæãæã䟡å€ããããŸãã
- x.EqualsïŒyïŒã¯ãy.EqualsïŒxïŒãšåãå€ãè¿ããŸãã
- ïŒx.EqualsïŒyïŒ&& y.EqualsïŒzïŒïŒãtrueãè¿ãå Žåãx.EqualsïŒzïŒã¯trueãè¿ããŸãã
- x.EqualsïŒnullïŒã¯falseãè¿ããŸãã
- x.yqualsïŒyïŒãé£ç¶ããŠåŒã³åºããšãxãšyã«ãã£ãŠåç
§ããããªããžã§ã¯ããå€æŽãããªãéããåãå€ãè¿ãããŸãã
- ãããŠãç¹ã«ãæµ®åå°æ°ç¹æ°ã®å€ãæ¯èŒããããã®èŠåã«é¢ããä»ã®å€ãã®ã
ãŸãã
GetHashCodeïŒïŒã¡ãœããã®
ããã¥ã¡ã³ãã«ã¯ãã¡ãœããã«ãã£ãŠè¿ãããå€ãå®æ°å€ã§ã¯ãªããšããèŠåãå«ãŸããŠããããããã£ã¹ã¯ãŸãã¯ããŒã¿ããŒã¹ã«ä¿åããŠããŒãšããŠäœ¿çšããªãã§ãã ããããªããžã§ã¯ãã®æ¯èŒã«äœ¿çšããå¿
èŠããããŸãïŒçãããªããªããžã§ã¯ãã¯åãããã·ã¥ã³ãŒããæã€ããšãã§ããŸãïŒãªã©ã
EqualsïŒObject ïŒã¡ãœãããš
GetHashCodeïŒïŒã¡ãœãããéè€ããPersonã¯ã©ã¹ïŒ
ã¯ã©ã¹Person using System; namespace HelloEquatable { public class Person { protected static string NormalizeName(string name) => name?.Trim() ?? string.Empty; protected static DateTime? NormalizeDate(DateTime? date) => date?.Date; public string FirstName { get; } public string LastName { get; } public DateTime? BirthDate { get; } public Person(string firstName, string lastName, DateTime? birthDate) { this.FirstName = NormalizeName(firstName); this.LastName = NormalizeName(lastName); this.BirthDate = NormalizeDate(birthDate); } public override int GetHashCode() => this.FirstName.GetHashCode() ^ this.LastName.GetHashCode() ^ this.BirthDate.GetHashCode(); protected static bool EqualsHelper(Person first, Person second) => first.BirthDate == second.BirthDate && first.FirstName == second.FirstName && first.LastName == second.LastName; public override bool Equals(object obj) { if ((object)this == obj) return true; var other = obj as Person; if ((object)other == null) return false; return EqualsHelper(this, other); } } }
GetHashCodeïŒïŒã¡ãœããã«é¢ãã泚æïŒ
- 䜿çšãããŠãããã£ãŒã«ãã®ããããã«nullãå«ãŸããŠããå Žåãå€GetHashCodeïŒïŒã®ä»£ããã«ãéåžžãŒãã䜿çšãããŸãã
- Personã¯ã©ã¹ã¯ãFirstNameããã³LastNameåç
§ãã£ãŒã«ãã«nullãå«ããããšã¯ã§ãããBirthDateãã£ãŒã«ãã¯NullableïŒOf TïŒæ§é ã§ãããå€ãæªå®çŸ©ã®å ŽåGetHashCodeïŒïŒã¯ãŒããè¿ãã GetHashCodeïŒïŒãåŒã³åºããããšãã«NullReferenceExceptionã¯ã¹ããŒãããªãããã«å®è£
ãããŸãçºçããŸãã
- Personã¯ã©ã¹ã®ãã£ãŒã«ãã«nullãå«ããããšãã§ããå Žåã GetHashCodeïŒïŒã¡ãœããã¯æ¬¡ã®ããã«å®è£
ãããŸãã
GetHashCodeïŒïŒ public override int GetHashCode() => this.FirstName?.GetHashCode() ?? 0 ^ this.LastName?.GetHashCode() ?? 0 ^ this.BirthDate?.GetHashCode() ?? 0;
EqualsïŒObjectïŒã¡ãœããã®å®è£
æ¹æ³ã詳现ã«æ€èšããŸãã
- ãŸããçŸåšã®ãªããžã§ã¯ãïŒ this ïŒãžã®ãªã³ã¯ãçä¿¡ãªããžã§ã¯ããžã®ãªã³ã¯ãšæ¯èŒããããªã³ã¯ãçããå Žåã¯trueãè¿ãããŸãïŒããã¯åããªããžã§ã¯ãã§ãããããã©ãŒãã³ã¹äžã®çç±ãå«ããå€ã«ããæ¯èŒã¯æå³ããããŸããïŒã
- 次ã«ã asæŒç®åã䜿çšã㊠ãå
¥åãªããžã§ã¯ããPersonåã«ãã£ã¹ããããŸãã ãã£ã¹ãã®çµæãnullã®å Žåã falseãè¿ãããŸãïŒçä¿¡ãªã³ã¯ãæåã¯nullã§ãã£ãããçä¿¡ãªããžã§ã¯ããPersonã¯ã©ã¹ãšäºææ§ã®ãªãã¿ã€ãã§ãããæããã«çŸåšã®ãªããžã§ã¯ããšçãããªãïŒã
- 次ã«ãPersonã¯ã©ã¹ã®2ã€ã®ãªããžã§ã¯ãã®ãã£ãŒã«ããå€ã§æ¯èŒããã察å¿ããçµæãè¿ãããŸãã
ã³ãŒãã®å¯èªæ§ãšå¯èœãªåå©çšã®ããã«ãå€ã«ãããªããžã§ã¯ãã®çŽæ¥æ¯èŒã¯EqualsHelperãã«ããŒã¡ãœããã§è¡ãããŸãã
ãããŸã§ãå€ããšã«ãªããžã§ã¯ããæ¯èŒããããã«æäœéå¿
èŠãªæ©èœã®ã¿ãå®è£
ããŸãããããã§ã«çåãçããŠããŸãã
æåã®è³ªåã¯ããçè«çã§ãã
EqualsïŒObjectïŒã¡ãœããã®èŠä»¶ã«æ³šæããŠãã ããã
x.Equals(null) returns false.
.NETæšæºã©ã€ãã©ãªã®ããã€ãã®ã€ã³ã¹ã¿ã³ã¹ã¡ãœããã
nullããã§ãã¯ããçç±ã«èå³ããããŸãããããšãã°ã
String.EqualsïŒObjectïŒã¡ãœããã¯æ¬¡ã®ããã«å®è£
ãããŸãã
String.EqualsïŒãªããžã§ã¯ãïŒ public override bool Equals(Object obj) { //this is necessary to guard against reverse-pinvokes and //other callers who do not use the callvirt instruction if (this == null) throw new NullReferenceException(); String str = obj as String; if (str == null) return false; if (Object.ReferenceEquals(this, obj)) return true; if (this.Length != str.Length) return false; return EqualsHelper(this, str); }
ã¡ãœããã®æåã®ã¹ãããã¯ã
ããã
nullãã©ããããã§ãã¯ãã
ããšã§ããè¯å®çãªçµæã®å Žåã
NullReferenceExceptionãã¹ããŒãããŸãã
ã³ã¡ã³ãã¯ã
ããã
nullã«ãªãå¯èœæ§ãããããšã瀺ã
ãŸã ã
ïŒã¡ãªã¿ã«ã
ãã㯠Stringã¯ã©ã¹ã§
ãªãŒããŒããŒãããã
==æŒç®åã䜿çšããŠ
nullãšæ¯èŒããããããããã©ãŒãã³ã¹ã®èŠ³ç¹ããã
ãããæ瀺çã«
ãªããžã§ã¯ãã«ãã£ã¹ãããŠç¢ºèªããããšãã
å§ãã
ãŸã ïŒïŒobjectïŒthis == nullããŸãã¯
Object.ReferenceEqualsã¡ãœããã䜿çšããŠ
ïŒãªããžã§ã¯ãããªããžã§ã¯ãïŒ ãåãã¡ãœããã®2çªç®ã®æ¯èŒã§è¡ãããŸããïŒ
ãããŠãããã«ã€ããŠã®è©³çŽ°ãèªãããšãã§ããèšäºãç»å ŽããŸããïŒ
this == nullïŒCLRã®äžçããã®æ¶ç©ºã®ç©èª ã
ãã ãããã®å Žåãã€ã³ã¹ã¿ã³ã¹ãäœæããã«ãªãŒããŒããŒããããPerson.EqualsïŒObjectïŒã¡ãœãããåŒã³åºããå
¥åãã©ã¡ãŒã¿ãŒãšããŠ
nullãæž¡ããšãã¡ãœããã®æåã®è¡ïŒifïŒïŒobjectïŒthis == objïŒreturn true;ïŒã¯
trueãè¿ã
ãŸãããã¯å®éã«ã¯æ£ãããã®ã§ãããã¡ãœããã®å®è£
ã®èŠä»¶ãšæ£åŒã«ççŸããŸãã
åæã«ãã¡ãœããã®
ããã¥ã¡ã³ãã§ã¯ãæåã«è¡ãã¹ãããšã¯
nullããã§ãã¯ãããã§ãã¯ãæåããå Žåã«äŸå€ãã¹ããŒããããšã瀺ãããŠããŸããã
ãã®å Žåãæåã®è¡ã§ãã¹ãŠã®ã¯ã©ã¹ã®ãã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹ã¡ãœããã§
nullããã§ãã¯ããã®ã¯äŸ¡å€ããã
ãŸãããããã¯ã°ãããŠããŸãã
ãããã£ãŠã
EqualsïŒObjectïŒã¡ãœãããå®è£
ããããã®å
¬åŒã®èŠä»¶ã¯ã次ã®ããã«æ確ã«ããå¿
èŠãããããã§ãã
- ïŒæ§é äœã§ã¯ãªãã¯ã©ã¹ã®å ŽåïŒçŸåšã®ãªããžã§ã¯ããšçä¿¡ãªããžã§ã¯ããžã®åç
§ãçããå Žåã trueãè¿ãããŸãã
- ãã§ã«2çªç®ã®èŠä»¶-çä¿¡ãªããžã§ã¯ããžã®åç
§ãnullã®å Žåã falseãè¿ãããŸãã
ãããã EqualsïŒObjectïŒã¡ãœããã®å®è£
ã«é¢ãã2çªç®ã®è³ªåã¯ããèå³æ·±ããã®ã§ããã䟡å€ããããŸãã
èŠä»¶ãæãæ£ããå®è£
ããæ¹æ³ã«é¢ãããã®ã§ãã
x.Equals(y) returns the same value as y.Equals(x).
ãããŠããã®ããŒãã®ã¡ãœããã®å®è£
ã®èŠä»¶ãšäŸã
ããã¥ã¡ã³ãã§å®å
šã«äžè²«ããŠ
ãããã©ãããããã³ãã®èŠä»¶ã®å®è£
ã«ä»£æ¿ã¢ãããŒãããããã©ããã
次ã®åºçç©ã§ã¯ãããã«ã€ããŠãããã³å€ã«ãã£ãŠãªããžã§ã¯ããæ¯èŒããããã®ã¯ã©ã¹ã®æŽç·Žã®å®å
šãªã»ããã®å®è£
ã«é¢ãã質åã«ã€ããŠèª¬æããŸãã