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