// Needed for NET35 (ThreadLocal) #if !NET_4_6 using System; using System.Collections.Generic; namespace LinqInternal.Threading.Needles { [Serializable] [System.Diagnostics.DebuggerNonUserCode] internal struct ReadOnlyStructNeedle : INeedle, IEquatable> { private readonly T _value; public ReadOnlyStructNeedle(T target) { _value = target; } T INeedle.Value { get { return _value; } set { throw new NotSupportedException(); } } public bool IsAlive { get { return !ReferenceEquals(_value, null); } } public T Value { get { return _value; } } public static explicit operator T(ReadOnlyStructNeedle needle) { return needle._value; } public static implicit operator ReadOnlyStructNeedle(T field) { return new ReadOnlyStructNeedle(field); } public static bool operator !=(ReadOnlyStructNeedle left, ReadOnlyStructNeedle right) { return NotEqualsExtracted(left, right); } public static bool operator ==(ReadOnlyStructNeedle left, ReadOnlyStructNeedle right) { return EqualsExtracted(left, right); } public override bool Equals(object obj) { if (obj is ReadOnlyStructNeedle) { return EqualsExtracted(this, (ReadOnlyStructNeedle)obj); } // Keep the "is" operator if (obj is T) { var target = _value; return IsAlive && EqualityComparer.Default.Equals(target, (T)obj); } return false; } public bool Equals(ReadOnlyStructNeedle other) { return EqualsExtracted(this, other); } public override int GetHashCode() { return base.GetHashCode(); } public override string ToString() { if (IsAlive) { return _value.ToString(); } return ""; } private static bool EqualsExtracted(ReadOnlyStructNeedle left, ReadOnlyStructNeedle right) { var leftValue = left._value; if (left.IsAlive) { var rightValue = right._value; return right.IsAlive && EqualityComparer.Default.Equals(leftValue, rightValue); } return !right.IsAlive; } private static bool NotEqualsExtracted(ReadOnlyStructNeedle left, ReadOnlyStructNeedle right) { var leftValue = left._value; if (left.IsAlive) { var rightValue = right._value; return !right.IsAlive || !EqualityComparer.Default.Equals(leftValue, rightValue); } return right.IsAlive; } } } #endif