1 // Licensed to the Apache Software Foundation(ASF) under one 2 // or more contributor license agreements.See the NOTICE file 3 // distributed with this work for additional information 4 // regarding copyright ownership.The ASF licenses this file 5 // to you under the Apache License, Version 2.0 (the 6 // "License"); you may not use this file except in compliance 7 // with the License. You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 using System.Collections; 19 using System.Collections.Generic; 20 21 namespace Thrift.Collections 22 { 23 // ReSharper disable once InconsistentNaming 24 public static class TCollections 25 { 26 /// <summary> 27 /// This will return true if the two collections are value-wise the same. 28 /// If the collection contains a collection, the collections will be compared using this method. 29 /// </summary> Equals(IEnumerable first, IEnumerable second)30 public static bool Equals(IEnumerable first, IEnumerable second) 31 { 32 if (first == null && second == null) 33 { 34 return true; 35 } 36 37 if (first == null || second == null) 38 { 39 return false; 40 } 41 42 // for dictionaries, we need to compare keys and values separately 43 // because KeyValuePair<K,V>.Equals() will not do what we want 44 var fdict = first as IDictionary; 45 var sdict = second as IDictionary; 46 if ((fdict != null) || (sdict != null)) 47 { 48 if ((fdict == null) || (sdict == null)) 49 return false; 50 return TCollections.Equals(fdict.Keys, sdict.Keys) 51 && TCollections.Equals(fdict.Values, sdict.Values); 52 } 53 54 var fiter = first.GetEnumerator(); 55 var siter = second.GetEnumerator(); 56 57 var fnext = fiter.MoveNext(); 58 var snext = siter.MoveNext(); 59 60 while (fnext && snext) 61 { 62 var fenum = fiter.Current as IEnumerable; 63 var senum = siter.Current as IEnumerable; 64 65 if (fenum != null && senum != null) 66 { 67 if (!Equals(fenum, senum)) 68 { 69 return false; 70 } 71 } 72 else if (fenum == null ^ senum == null) 73 { 74 return false; 75 } 76 else if (!Equals(fiter.Current, siter.Current)) 77 { 78 return false; 79 } 80 81 fnext = fiter.MoveNext(); 82 snext = siter.MoveNext(); 83 } 84 85 return fnext == snext; 86 } 87 88 /// <summary> 89 /// This returns a hashcode based on the value of the enumerable. 90 /// </summary> GetHashCode(IEnumerable enumerable)91 public static int GetHashCode(IEnumerable enumerable) 92 { 93 if (enumerable == null) 94 { 95 return 0; 96 } 97 98 var hashcode = 0; 99 100 foreach (var obj in enumerable) 101 { 102 var enum2 = obj as IEnumerable; 103 var objHash = enum2 == null ? obj.GetHashCode() : GetHashCode(enum2); 104 105 unchecked 106 { 107 hashcode = (hashcode * 397) ^ (objHash); 108 } 109 } 110 111 return hashcode; 112 } 113 114 115 } 116 } 117