1 // 2 // Copyright (c) ZeroC, Inc. All rights reserved. 3 // 4 5 namespace Ice 6 { 7 public class CollectionComparer 8 { 9 // 10 // Try to compare two collections efficiently, by doing a reference 11 // and count comparison. If equality or inequality can be determined 12 // this way, 'result' contains the outcome of the comparison and the 13 // return value is true. Otherwise, if equality or inequality cannot 14 // be determined this way, 'result' and return value are both false. 15 // cheapComparison(System.Collections.ICollection c1, System.Collections.ICollection c2, out bool result)16 private static bool cheapComparison(System.Collections.ICollection c1, 17 System.Collections.ICollection c2, 18 out bool result) 19 { 20 if(ReferenceEquals(c1, c2)) 21 { 22 result = true; 23 return true; // Equal references means the collections are equal. 24 } 25 if(c1 == null || c2 == null) 26 { 27 result = false; 28 return true; // The references are not equal and one of them is null, so c1 and c2 are not equal. 29 } 30 if(c1.Count != c2.Count) 31 { 32 result = false; 33 return true; // Different number of elements, so c1 and c2 are not equal. 34 } 35 if(c1.Count == 0) 36 { 37 result = true; 38 return true; // Same number of elements, both zero, so c1 and c2 are equal. 39 } 40 41 result = false; // Couldn't get a result cheaply. 42 return false; // c1 and c2 may still be equal, but we have to compare elements to find out. 43 } 44 45 // 46 // Compare two dictionaries for value equality (as implemented by the Equals() method of its elements). 47 // Equals(System.Collections.IDictionary d1, System.Collections.IDictionary d2)48 public static bool Equals(System.Collections.IDictionary d1, System.Collections.IDictionary d2) 49 { 50 try 51 { 52 bool result; 53 if(cheapComparison(d1, d2, out result)) 54 { 55 return result; 56 } 57 58 System.Collections.ICollection keys1 = d1.Keys; 59 foreach(object k in keys1) 60 { 61 if(d2.Contains(k)) 62 { 63 object v1 = d1[k]; 64 object v2 = d2[k]; 65 if(v1 == null) 66 { 67 if(v2 != null) 68 { 69 return false; 70 } 71 } 72 else 73 { 74 if(!v1.Equals(v2)) 75 { 76 return false; 77 } 78 } 79 } 80 else 81 { 82 return false; 83 } 84 } 85 } 86 catch(System.Exception) 87 { 88 return false; 89 } 90 91 return true; 92 } 93 94 // 95 // Compare two collections for equality (as implemented by the Equals() method of its elements). 96 // Order is significant. 97 // Equals(System.Collections.ICollection c1, System.Collections.ICollection c2)98 public static bool Equals(System.Collections.ICollection c1, System.Collections.ICollection c2) 99 { 100 try 101 { 102 bool result; 103 if(cheapComparison(c1, c2, out result)) 104 { 105 return result; 106 } 107 108 System.Collections.IEnumerator e = c2.GetEnumerator(); 109 foreach(object o in c1) 110 { 111 e.MoveNext(); 112 if(!Equals(o, e.Current)) 113 { 114 return false; 115 } 116 } 117 return true; 118 } 119 catch(System.Exception) 120 { 121 return false; 122 } 123 } 124 125 // 126 // Compare two collections for equality (as implemented by the Equals() method of its elements). 127 // Order is significant. 128 // Equals(System.Collections.IEnumerable c1, System.Collections.IEnumerable c2)129 public static bool Equals(System.Collections.IEnumerable c1, System.Collections.IEnumerable c2) 130 { 131 try 132 { 133 if(ReferenceEquals(c1, c2)) 134 { 135 return true; // Equal references means the collections are equal. 136 } 137 if(c1 == null || c2 == null) 138 { 139 return false; // The references are not equal and one of them is null, so c1 and c2 are not equal. 140 } 141 142 System.Collections.IEnumerator e1 = c1.GetEnumerator(); 143 System.Collections.IEnumerator e2 = c2.GetEnumerator(); 144 while(e1.MoveNext()) 145 { 146 if(!e2.MoveNext()) 147 { 148 return false; // c2 has fewer elements than c1. 149 } 150 if(e1.Current == null) 151 { 152 if(e2.Current != null) 153 { 154 return false; 155 } 156 } 157 else 158 { 159 if(!e1.Current.Equals(e2.Current)) 160 { 161 return false; 162 } 163 } 164 } 165 if(e2.MoveNext()) 166 { 167 return false; // c2 has more elements than c1. 168 } 169 return true; 170 } 171 catch(System.Exception) 172 { 173 return false; 174 } 175 } 176 } 177 } 178