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 
20 namespace Thrift.Collections
21 {
22     // ReSharper disable once InconsistentNaming
23     public class TCollections
24     {
25         /// <summary>
26         ///     This will return true if the two collections are value-wise the same.
27         ///     If the collection contains a collection, the collections will be compared using this method.
28         /// </summary>
Equals(IEnumerable first, IEnumerable second)29         public static bool Equals(IEnumerable first, IEnumerable second)
30         {
31             if (first == null && second == null)
32             {
33                 return true;
34             }
35 
36             if (first == null || second == null)
37             {
38                 return false;
39             }
40 
41             var fiter = first.GetEnumerator();
42             var siter = second.GetEnumerator();
43 
44             var fnext = fiter.MoveNext();
45             var snext = siter.MoveNext();
46 
47             while (fnext && snext)
48             {
49                 var fenum = fiter.Current as IEnumerable;
50                 var senum = siter.Current as IEnumerable;
51 
52                 if (fenum != null && senum != null)
53                 {
54                     if (!Equals(fenum, senum))
55                     {
56                         return false;
57                     }
58                 }
59                 else if (fenum == null ^ senum == null)
60                 {
61                     return false;
62                 }
63                 else if (!Equals(fiter.Current, siter.Current))
64                 {
65                     return false;
66                 }
67 
68                 fnext = fiter.MoveNext();
69                 snext = siter.MoveNext();
70             }
71 
72             return fnext == snext;
73         }
74 
75         /// <summary>
76         ///     This returns a hashcode based on the value of the enumerable.
77         /// </summary>
GetHashCode(IEnumerable enumerable)78         public static int GetHashCode(IEnumerable enumerable)
79         {
80             if (enumerable == null)
81             {
82                 return 0;
83             }
84 
85             var hashcode = 0;
86 
87             foreach (var obj in enumerable)
88             {
89                 var enum2 = obj as IEnumerable;
90                 var objHash = enum2 == null ? obj.GetHashCode() : GetHashCode(enum2);
91 
92                 unchecked
93                 {
94                     hashcode = (hashcode*397) ^ (objHash);
95                 }
96             }
97 
98             return hashcode;
99         }
100     }
101 }