1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System
.Collections
.Generic
;
6 using System
.Runtime
.Versioning
;
10 // Because we have special type system support that says a boxed Nullable<T>
11 // can be used where a boxed<T> is use, Nullable<T> can not implement any intefaces
12 // at all (since T may not). Do NOT add any interfaces to Nullable!
15 [NonVersionable
] // This only applies to field layout
16 [System
.Runtime
.CompilerServices
.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
17 public partial struct Nullable
<T
> where T
: struct
19 private readonly bool hasValue
; // Do not rename (binary serialization)
20 internal T
value; // Do not rename (binary serialization) or make readonly (can be mutated in ToString, etc.)
23 public Nullable(T
value)
44 ThrowHelper
.ThrowInvalidOperationException_InvalidOperation_NoValue();
51 public T
GetValueOrDefault()
57 public T
GetValueOrDefault(T defaultValue
)
59 return hasValue
? value : defaultValue
;
62 public override bool Equals(object? other
)
64 if (!hasValue
) return other
== null;
65 if (other
== null) return false;
66 return value.Equals(other
);
69 public override int GetHashCode()
71 return hasValue
? value.GetHashCode() : 0;
74 public override string? ToString()
76 return hasValue
? value.ToString() : "";
80 public static implicit operator Nullable
<T
>(T
value)
82 return new Nullable
<T
>(value);
86 public static explicit operator T(Nullable
<T
> value)
92 public static class Nullable
94 public static int Compare
<T
>(Nullable
<T
> n1
, Nullable
<T
> n2
) where T
: struct
98 if (n2
.HasValue
) return Comparer
<T
>.Default
.Compare(n1
.value, n2
.value);
101 if (n2
.HasValue
) return -1;
105 public static bool Equals
<T
>(Nullable
<T
> n1
, Nullable
<T
> n2
) where T
: struct
109 if (n2
.HasValue
) return EqualityComparer
<T
>.Default
.Equals(n1
.value, n2
.value);
112 if (n2
.HasValue
) return false;
116 // If the type provided is not a Nullable Type, return null.
117 // Otherwise, returns the underlying type of the Nullable type
118 public static Type
? GetUnderlyingType(Type nullableType
)
120 if ((object)nullableType
== null)
122 throw new ArgumentNullException(nameof(nullableType
));
126 // This is necessary to handle types without reflection metadata
127 if (nullableType
.TryGetEEType(out EETypePtr nullableEEType
))
129 if (nullableEEType
.IsGeneric
)
131 if (nullableEEType
.IsNullable
)
133 return Internal
.Reflection
.Core
.NonPortable
.RuntimeTypeUnifier
.GetRuntimeTypeForEEType(nullableEEType
.NullableType
);
140 if (nullableType
.IsGenericType
&& !nullableType
.IsGenericTypeDefinition
)
142 // instantiated generic type only
143 Type genericType
= nullableType
.GetGenericTypeDefinition();
144 if (object.ReferenceEquals(genericType
, typeof(Nullable
<>)))
146 return nullableType
.GetGenericArguments()[0];