1 // 2 // Copyright (c) ZeroC, Inc. All rights reserved. 3 // 4 5 namespace Ice 6 { 7 using System; 8 using System.Collections.Generic; 9 using System.Runtime.Serialization; 10 11 public struct NoneType 12 { 13 } 14 15 /// <summary> 16 /// Encapsulates an optional value. Instances of this type are immutable. 17 /// </summary> 18 [Serializable] 19 public struct Optional<T> : ISerializable 20 { 21 /// <summary> 22 /// Creates an optional value whose state is unset. 23 /// </summary> OptionalIce.Optional24 public Optional(NoneType none) 25 { 26 _value = default(T); 27 _isSet = false; 28 } 29 30 /// <summary> 31 /// Creates an optional value and sets its value to the given argument. 32 /// </summary> OptionalIce.Optional33 public Optional(T v) 34 { 35 _value = v; 36 _isSet = true; 37 } 38 39 /// <summary> 40 /// Creates an optional value whose state is copied from the given argument. 41 /// </summary> OptionalIce.Optional42 public Optional(Optional<T> v) 43 { 44 _value = v._value; 45 _isSet = v._isSet; 46 } 47 48 /// <summary> 49 /// Initializes a new instance of the exception with serialized data. 50 /// </summary> 51 /// <param name="info">Holds the serialized object data about the exception being thrown.</param> 52 /// <param name="context">Contains contextual information about the source or destination.</param> OptionalIce.Optional53 public Optional(SerializationInfo info, StreamingContext context) 54 { 55 _isSet = info.GetBoolean("isSet"); 56 if(_isSet) 57 { 58 _value = (T)info.GetValue("value", typeof(T)); 59 } 60 else 61 { 62 _value = default(T); 63 } 64 } 65 66 /// <summary> 67 /// Conversion operator to the underlying type; a cast is required. An exception 68 /// is raised if no value is set. 69 /// </summary> 70 /// <returns>The encapsulated value.</returns> 71 /// <exception cref="System.InvalidOperationException">Thrown if no value is set.</exception> operator TIce.Optional72 public static explicit operator T(Optional<T> v) 73 { 74 return v.Value; 75 } 76 77 /// <summary> 78 /// Conversion operator from a value of the underlying type; no cast is required. 79 /// </summary> operator Optional<T>Ice.Optional80 public static implicit operator Optional<T>(T v) 81 { 82 return new Optional<T>(v); 83 } 84 85 /// <summary> 86 /// Conversion operator from a None value; no cast is required. 87 /// </summary> operator Optional<T>Ice.Optional88 public static implicit operator Optional<T>(NoneType v) 89 { 90 return new Optional<T>(); 91 } 92 93 /// <summary> 94 /// Reads and writes the encapsulated value. 95 /// </summary> 96 /// <exception cref="System.InvalidOperationException">Thrown if the property is read and no value is 97 /// set.</exception> 98 public T Value 99 { 100 get 101 { 102 if(!_isSet) 103 { 104 throw new InvalidOperationException(); 105 } 106 return _value; 107 } 108 } 109 110 /// <summary> 111 /// Determines whether a value is set. 112 /// </summary> 113 /// <returns>True if a value is set, false otherwise.</returns> 114 public bool HasValue 115 { 116 get 117 { 118 return _isSet; 119 } 120 } 121 EqualsIce.Optional122 public override bool Equals(object other) 123 { 124 if(ReferenceEquals(this, other)) 125 { 126 return true; 127 } 128 if(other == null) 129 { 130 return false; 131 } 132 133 try 134 { 135 Optional<T> o2 = (Optional<T>)other; 136 137 if(_isSet != o2._isSet) 138 { 139 return false; 140 } 141 else if(_isSet) 142 { 143 EqualityComparer<T> comparer = EqualityComparer<T>.Default; 144 return comparer.Equals(_value, o2._value); 145 } 146 147 return true; 148 } 149 catch(System.Exception) 150 { 151 return false; 152 } 153 } 154 GetHashCodeIce.Optional155 public override int GetHashCode() 156 { 157 if(!_isSet) 158 { 159 return base.GetHashCode(); 160 } 161 else 162 { 163 return _value.GetHashCode(); 164 } 165 } 166 167 /// <summary> 168 /// Serializes an optional value. 169 /// </summary> 170 /// <param name="info">Holds the serialized object data about the exception being thrown.</param> 171 /// <param name="context">Contains contextual information about the source or destination.</param> GetObjectDataIce.Optional172 public void GetObjectData(SerializationInfo info, StreamingContext context) 173 { 174 info.AddValue("isSet", _isSet); 175 if(_isSet) 176 { 177 info.AddValue("value", _value, typeof(T)); 178 } 179 } 180 181 private T _value; 182 private bool _isSet; 183 } 184 185 /// <summary> 186 /// The optional format. 187 /// 188 /// An optional value is encoded with a specific optional format. This optional 189 /// format describes how the data is encoded and how it can be skipped by the 190 /// unmarshaling code if the optional is not known to the receiver. 191 /// </summary> 192 public enum OptionalFormat 193 { 194 F1 = 0, 195 F2 = 1, 196 F4 = 2, 197 F8 = 3, 198 Size = 4, 199 VSize = 5, 200 FSize = 6, 201 Class = 7 202 } 203 } 204