0
|
1 using System;
|
|
2 using System.Collections;
|
|
3
|
|
4 namespace BLToolkit.Common
|
|
5 {
|
|
6 public class CompoundValue : IComparable, IEquatable<CompoundValue>
|
|
7 {
|
|
8 public CompoundValue(params object[] values)
|
|
9 {
|
|
10 if (values == null)
|
|
11 throw new ArgumentNullException("values");
|
|
12
|
|
13 // Note that the compound hash is precalculated.
|
|
14 // This means that CompoundValue can be used only with immutable values.
|
|
15 // Otherwise the behaviour is undefined.
|
|
16 //
|
|
17 _hash = CalcHashCode(values);
|
|
18 _values = values;
|
|
19 }
|
|
20
|
|
21 private readonly object[] _values;
|
|
22 private readonly int _hash;
|
|
23
|
|
24 public int Count
|
|
25 {
|
|
26 get { return _values == null ? 0 : _values.Length; }
|
|
27 }
|
|
28
|
|
29 public object this[int index]
|
|
30 {
|
|
31 get { return _values == null ? null : _values[index]; }
|
|
32 }
|
|
33
|
|
34 private static int CalcHashCode(object[] values)
|
|
35 {
|
|
36 if (values.Length == 0)
|
|
37 return 0;
|
|
38
|
|
39 object o = values[0];
|
|
40 int hash = o == null ? 0 : o.GetHashCode();
|
|
41
|
|
42 for (int i = 1; i < values.Length; i++)
|
|
43 {
|
|
44 o = values[i];
|
|
45 hash = ((hash << 5) + hash) ^ (o == null ? 0 : o.GetHashCode());
|
|
46 }
|
|
47
|
|
48 return hash;
|
|
49 }
|
|
50
|
|
51 #region IComparable Members
|
|
52
|
|
53 public int CompareTo(object obj)
|
|
54 {
|
|
55 var objValues = ((CompoundValue)obj)._values;
|
|
56
|
|
57 if (_values.Length != objValues.Length)
|
|
58 return _values.Length - objValues.Length;
|
|
59
|
|
60 for (var i = 0; i < _values.Length; i++)
|
|
61 {
|
|
62 var n = Comparer.Default.Compare(_values[i], objValues[i]);
|
|
63
|
|
64 if (n != 0)
|
|
65 return n;
|
|
66 }
|
|
67
|
|
68 return 0;
|
|
69 }
|
|
70
|
|
71 #endregion
|
|
72
|
|
73 #region Object Overrides
|
|
74
|
|
75 public override int GetHashCode()
|
|
76 {
|
|
77 return _hash;
|
|
78 }
|
|
79
|
|
80 public override bool Equals(object obj)
|
|
81 {
|
|
82 if (!(obj is CompoundValue))
|
|
83 return false;
|
|
84
|
|
85 return Equals((CompoundValue)obj);
|
|
86 }
|
|
87
|
|
88 #endregion
|
|
89
|
|
90 #region IEquatable<CompoundValue> Members
|
|
91
|
|
92 public bool Equals(CompoundValue other)
|
|
93 {
|
|
94 if (_hash != other._hash)
|
|
95 return false;
|
|
96
|
|
97 object[] values = other._values;
|
|
98
|
|
99 if (_values.Length != values.Length)
|
|
100 return false;
|
|
101
|
|
102 for (int i = 0; i < _values.Length; i++)
|
|
103 {
|
|
104 object x = _values[i];
|
|
105 object y = values[i];
|
|
106
|
|
107 if (x == null && y == null)
|
|
108 continue;
|
|
109
|
|
110 if (x == null || y == null)
|
|
111 return false;
|
|
112
|
|
113 if (x.Equals(y) == false)
|
|
114 return false;
|
|
115 }
|
|
116
|
|
117 return true;
|
|
118 }
|
|
119
|
|
120 #endregion
|
|
121 }
|
|
122 }
|