2008-08-21 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / System / Nullable.cs
1 //
2 // System.Nullable.cs
3 //
4 // Martin Baulig (martin@ximian.com)
5 // Marek Safar   (marek.safar@gmail.com)
6 //
7 // (C) 2004 Novell, Inc.
8 //
9
10 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 #if NET_2_0
34
35 using System.Reflection;
36 using System.Collections.Generic;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
39
40 namespace System
41 {
42         [ComVisible (true)]
43         public static class Nullable {
44
45 #if NET_2_1
46                 [ComVisible (false)]
47 #endif
48                 public static int Compare<T> (T? value1, T? value2) where T: struct
49                 {
50                         if (value1.has_value) {
51                                 if (!value2.has_value)
52                                         return 1;
53
54                                 return Comparer<T>.Default.Compare (value1.value, value2.value);
55                         }
56                         
57                         return value2.has_value ? -1 : 0;
58                 }
59
60 #if NET_2_1
61                 [ComVisible (false)]
62 #endif
63                 public static bool Equals<T> (T? value1, T? value2) where T: struct
64                 {
65                         if (value1.has_value != value2.has_value)
66                                 return false;
67
68                         if (!value1.has_value)
69                                 return true;
70
71                         return EqualityComparer<T>.Default.Equals (value1.value, value2.value);
72                 }
73
74                 public static Type GetUnderlyingType (Type nullableType)
75                 {
76                         if (nullableType == null)
77                                 throw new ArgumentNullException ("nullableType");
78                         if (nullableType.IsGenericType && nullableType.GetGenericTypeDefinition () == typeof (Nullable<>))
79                                 return nullableType.GetGenericArguments ()[0];
80                         else
81                                 return null;
82                 }
83         }
84
85         [Serializable]
86         public struct Nullable<T> where T: struct
87         {
88                 #region Sync with runtime code
89                 internal T value;
90                 internal bool has_value;
91                 #endregion
92
93                 public Nullable (T value)
94                 {
95                         this.has_value = true;
96                         this.value = value;
97                 }
98
99                 public bool HasValue {
100                         get { return has_value; }
101                 }
102
103                 public T Value {
104                         get { 
105                                 if (!has_value)
106                                         throw new InvalidOperationException ("Nullable object must have a value.");
107                                 
108                                 return value; 
109                         }
110                 }
111
112                 public override bool Equals (object other)
113                 {
114                         if (other == null)
115                                 return has_value == false;
116                         if (!(other is Nullable<T>))
117                                 return false;
118
119                         return Equals ((Nullable <T>) other);
120                 }
121
122                 bool Equals (Nullable<T> other)
123                 {
124                         if (other.has_value != has_value)
125                                 return false;
126
127                         if (has_value == false)
128                                 return true;
129
130                         return other.value.Equals (value);
131                 }
132
133                 public override int GetHashCode ()
134                 {
135                         if (!has_value)
136                                 return 0;
137
138                         return value.GetHashCode ();
139                 }
140
141                 public T GetValueOrDefault ()
142                 {
143                         return GetValueOrDefault (default (T));
144                 }
145
146                 public T GetValueOrDefault (T defaultValue)
147                 {
148                         if (!has_value)
149                                 return defaultValue;
150                         else
151                                 return value;
152                 }
153
154                 public override string ToString ()
155                 {
156                         if (has_value)
157                                 return value.ToString ();
158                         else
159                                 return String.Empty;
160                 }
161
162                 public static implicit operator Nullable<T> (T value)
163                 {
164                         return new Nullable<T> (value);
165                 }
166
167                 public static explicit operator T (Nullable<T> value)
168                 {
169                         return value.Value;
170                 }
171
172                 //
173                 // These are called by the JIT
174                 //
175                 
176                 //
177                 // JIT implementation of box valuetype System.Nullable`1<T>
178                 //
179                 static object Box (T? o)
180                 {
181                         if (!o.has_value)
182                                 return null;
183                                 
184                         return o.value;
185                 }
186                 
187                 static T? Unbox (object o)
188                 {
189                         if (o == null)
190                                 return null;
191                         return (T) o;
192                 }
193         }
194 }
195 #endif