11using ICU4N . Support . Collections ;
22using ICU4N . Util ;
33using J2N . Collections ;
4+ using J2N . Collections . Generic ;
5+ using J2N . Text ;
46using System ;
57using System . Collections ;
68using System . Collections . Generic ;
@@ -34,21 +36,31 @@ public static Relation<TKey, TValue> Of<TKey, TValue>(IDictionary<TKey, ISet<TVa
3436 /// <typeparam name="TKey">Type of key.</typeparam>
3537 /// <typeparam name="TValue">Type of value.</typeparam>
3638 /// <author>medavis</author>
37- public class Relation < TKey , TValue > : IFreezable < Relation < TKey , TValue > > , IEnumerable < KeyValuePair < TKey , TValue > >
39+ public class Relation < TKey , TValue > : IFreezable < Relation < TKey , TValue > > , IEnumerable < KeyValuePair < TKey , TValue > > , IStructuralEquatable
3840 where TValue : class // ICU4N specific - using only reference types so we don't have to change from null to default(TValue)
3941 {
4042 private IDictionary < TKey , ISet < TValue > > data ;
4143
4244 ConstructorInfo setCreator ;
4345 object [ ] setComparerParam ;
4446
47+ private readonly DictionaryEqualityComparer < TKey , ISet < TValue > > structuralEqualityComparer ;
48+
4549 public Relation ( IDictionary < TKey , ISet < TValue > > map , Type setCreator )
46- : this ( map , setCreator , null )
47- {
48- }
50+ : this ( map , setCreator , null , DictionaryEqualityComparer < TKey , ISet < TValue > > . Aggressive ) // ICU4N TODO: Factor out Aggressive mode
51+ { }
52+
53+ public Relation ( IDictionary < TKey , ISet < TValue > > map , Type setCreator , DictionaryEqualityComparer < TKey , ISet < TValue > > structuralEqualityComparer )
54+ : this ( map , setCreator , null , structuralEqualityComparer )
55+ { }
4956
5057 public Relation ( IDictionary < TKey , ISet < TValue > > map , Type setCreator , IComparer < TValue > setComparator )
58+ : this ( map , setCreator , null , DictionaryEqualityComparer < TKey , ISet < TValue > > . Aggressive ) // ICU4N TODO: Factor out Aggressive mode
59+ { }
60+
61+ public Relation ( IDictionary < TKey , ISet < TValue > > map , Type setCreator , IComparer < TValue > setComparator , DictionaryEqualityComparer < TKey , ISet < TValue > > structuralEqualityComparer )
5162 {
63+ this . structuralEqualityComparer = structuralEqualityComparer ?? throw new ArgumentNullException ( nameof ( structuralEqualityComparer ) ) ;
5264 try
5365 {
5466 setComparerParam = setComparator == null ? null : new object [ ] { setComparator } ;
@@ -178,9 +190,9 @@ public override bool Equals(object o)
178190 {
179191 if ( o == null )
180192 return false ;
181- if ( o . GetType ( ) != this . GetType ( ) )
182- return false ;
183- return data . Equals ( ( ( Relation < TKey , TValue > ) o ) . data ) ;
193+ if ( o is Relation < TKey , TValue > otherRelation )
194+ return structuralEqualityComparer . Equals ( this . data , otherRelation . data ) ;
195+ return false ;
184196 }
185197
186198 // public V get(Object key) {
@@ -202,9 +214,25 @@ public ISet<TValue> Get(TKey key)
202214
203215 public override int GetHashCode ( )
204216 {
205- return CollectionUtil . GetHashCode ( data ) ;
217+ return structuralEqualityComparer . GetHashCode ( data ) ;
218+ }
219+
220+ #region IStructualEquatable Members
221+
222+ public bool Equals ( object other , IEqualityComparer comparer )
223+ {
224+ if ( other is Relation < TKey , TValue > otherRelation )
225+ return structuralEqualityComparer . Equals ( this . data , otherRelation . data ) ;
226+ return false ;
227+ }
228+
229+ public int GetHashCode ( IEqualityComparer comparer )
230+ {
231+ return structuralEqualityComparer . GetHashCode ( data ) ;
206232 }
207233
234+ #endregion
235+
208236 //public virtual bool IsEmpty // ICU4N specific - removed because this is not .NET-like
209237 //{
210238 // get { return data.Count == 0; }
@@ -347,7 +375,7 @@ public virtual C GetValues<C>(C result)
347375
348376 public override string ToString ( )
349377 {
350- return CollectionUtil . ToString ( data ) ;
378+ return string . Format ( StringFormatter . CurrentCulture , "{0}" , data ) ;
351379 }
352380
353381 // ICU4N specific - SimpleEntry class not needed, since we have implemented IEnumerator.
0 commit comments