// ********************************************************************** // // Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** namespace Ice { using System; using System.Collections.Generic; using System.Runtime.Serialization; public struct NoneType { } /// /// Encapsulates an optional value. Instances of this type are immutable. /// #if SILVERLIGHT public struct Optional #else [Serializable] public struct Optional : ISerializable #endif { /// /// Creates an optional value whose state is unset. /// public Optional(NoneType none) { _value = default(T); _isSet = false; } /// /// Creates an optional value and sets its value to the given argument. /// public Optional(T v) { _value = v; _isSet = true; } /// /// Creates an optional value whose state is copied from the given argument. /// public Optional(Optional v) { _value = v._value; _isSet = v._isSet; } #if !SILVERLIGHT /// /// Initializes a new instance of the exception with serialized data. /// /// Holds the serialized object data about the exception being thrown. /// Contains contextual information about the source or destination. public Optional(SerializationInfo info, StreamingContext context) { _isSet = info.GetBoolean("isSet"); if(_isSet) { _value = (T)info.GetValue("value", typeof(T)); } else { _value = default(T); } } #endif /// /// Conversion operator to the underlying type; a cast is required. An exception /// is raised if no value is set. /// /// The encapsulated value. /// Thrown if no value is set. public static explicit operator T(Optional v) { return v.Value; } /// /// Conversion operator from a value of the underlying type; no cast is required. /// public static implicit operator Optional(T v) { return new Optional(v); } /// /// Conversion operator from a None value; no cast is required. /// public static implicit operator Optional(NoneType v) { return new Optional(); } /// /// Reads and writes the encapsulated value. /// /// Thrown if the property is read and no value is /// set. public T Value { get { if(!_isSet) { throw new System.InvalidOperationException(); } return _value; } } /// /// Determines whether a value is set. /// /// True if a value is set, false otherwise. public bool HasValue { get { return _isSet; } } public override bool Equals(object other) { if(object.ReferenceEquals(this, other)) { return true; } if(other == null) { return false; } try { Optional o2 = (Optional)other; if(_isSet != o2._isSet) { return false; } else if(_isSet) { EqualityComparer comparer = EqualityComparer.Default; return comparer.Equals(_value, o2._value); } return true; } catch(System.Exception) { return false; } } public override int GetHashCode() { if(!_isSet) { return base.GetHashCode(); } else { return _value.GetHashCode(); } } #if !SILVERLIGHT /// /// Serializes an optional value. /// /// Holds the serialized object data about the exception being thrown. /// Contains contextual information about the source or destination. public void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("isSet", _isSet); if(_isSet) { info.AddValue("value", _value, typeof(T)); } } #endif private T _value; private bool _isSet; } /// /// Handles callbacks for an optional object parameter. /// public class OptionalPatcher : IceInternal.Patcher where T : Ice.Object { /// /// Instantiates the class with the given optional. /// /// The Slice type ID corresponding to the formal type. public OptionalPatcher(string type) : base(type) { } /// /// Sets the Ice object of the optional to the passed instance. /// /// The new object for the optional. public override void patch(Ice.Object v) { if(v == null || typeof(T).IsAssignableFrom(v.GetType())) { // // The line below must assign to the Value property. We could also // have written it this way: // // this.opt = (T)v; // // However, when v is null, the optional might be cleared, which // is not the result we want. // this.value = new Optional((T)v); } else { IceInternal.Ex.throwUOE(type(), v.ice_id()); } } /// /// The target optional. /// public Optional value = new Optional(); } /// /// The optional format. /// /// An optional value is encoded with a specific optional format. This optional /// format describes how the data is encoded and how it can be skipped by the /// unmarshaling code if the optional is not known to the receiver. /// public enum OptionalFormat { F1 = 0, F2 = 1, F4 = 2, F8 = 3, Size = 4, VSize = 5, FSize = 6, Class = 7 } }