Mercurial > pub > bltoolkit
diff Source/Common/CompoundValue.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Source/Common/CompoundValue.cs Thu Mar 27 21:46:09 2014 +0400 @@ -0,0 +1,122 @@ +using System; +using System.Collections; + +namespace BLToolkit.Common +{ + public class CompoundValue : IComparable, IEquatable<CompoundValue> + { + public CompoundValue(params object[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + + // Note that the compound hash is precalculated. + // This means that CompoundValue can be used only with immutable values. + // Otherwise the behaviour is undefined. + // + _hash = CalcHashCode(values); + _values = values; + } + + private readonly object[] _values; + private readonly int _hash; + + public int Count + { + get { return _values == null ? 0 : _values.Length; } + } + + public object this[int index] + { + get { return _values == null ? null : _values[index]; } + } + + private static int CalcHashCode(object[] values) + { + if (values.Length == 0) + return 0; + + object o = values[0]; + int hash = o == null ? 0 : o.GetHashCode(); + + for (int i = 1; i < values.Length; i++) + { + o = values[i]; + hash = ((hash << 5) + hash) ^ (o == null ? 0 : o.GetHashCode()); + } + + return hash; + } + + #region IComparable Members + + public int CompareTo(object obj) + { + var objValues = ((CompoundValue)obj)._values; + + if (_values.Length != objValues.Length) + return _values.Length - objValues.Length; + + for (var i = 0; i < _values.Length; i++) + { + var n = Comparer.Default.Compare(_values[i], objValues[i]); + + if (n != 0) + return n; + } + + return 0; + } + + #endregion + + #region Object Overrides + + public override int GetHashCode() + { + return _hash; + } + + public override bool Equals(object obj) + { + if (!(obj is CompoundValue)) + return false; + + return Equals((CompoundValue)obj); + } + + #endregion + + #region IEquatable<CompoundValue> Members + + public bool Equals(CompoundValue other) + { + if (_hash != other._hash) + return false; + + object[] values = other._values; + + if (_values.Length != values.Length) + return false; + + for (int i = 0; i < _values.Length; i++) + { + object x = _values[i]; + object y = values[i]; + + if (x == null && y == null) + continue; + + if (x == null || y == null) + return false; + + if (x.Equals(y) == false) + return false; + } + + return true; + } + + #endregion + } +}