C# Language
Nullable types
Zoeken…
Syntaxis
-
Nullable<int> i = 10;
- int? j = 11;
- int? k = nul;
- Datum Tijd? DateOfBirth = DateTime.Now;
- decimale? Hoeveelheid = 1,0 m;
- bool? IsAvailable = true;
- char? Letter = 'a';
- (type)? variableName
Opmerkingen
Nullable-typen kunnen alle waarden van een onderliggend type en null
.
De syntaxis T?
is steno voor Nullable<T>
Nullable-waarden zijn eigenlijk System.ValueType
objecten, dus ze kunnen in en uit de doos worden geplaatst. Ook is de null
van een nullable object niet hetzelfde als de null
van een referentieobject, het is gewoon een vlag.
Wanneer een nulpunt van een object boksen, wordt de nulwaarde geconverteerd naar null
en wordt een niet-nulwaarde omgezet in een niet-nulbaar onderliggend type.
DateTime? dt = null;
var o = (object)dt;
var result = (o == null); // is true
DateTime? dt = new DateTime(2015, 12, 11);
var o = (object)dt;
var dt2 = (DateTime)dt; // correct cause o contains DateTime value
De tweede regel leidt tot correcte, maar paradoxale code:
DateTime? dt = new DateTime(2015, 12, 11);
var o = (object)dt;
var type = o.GetType(); // is DateTime, not Nullable<DateTime>
In het kort:
DateTime? dt = new DateTime(2015, 12, 11);
var type = dt.GetType(); // is DateTime, not Nullable<DateTime>
Een nullabel initialiseren
Voor null
:
Nullable<int> i = null;
Of:
int? i = null;
Of:
var i = (int?)null;
Voor niet-nulwaarden:
Nullable<int> i = 0;
Of:
int? i = 0;
Controleer of een Nullable een waarde heeft
int? i = null;
if (i != null)
{
Console.WriteLine("i is not null");
}
else
{
Console.WriteLine("i is null");
}
Wat hetzelfde is als:
if (i.HasValue)
{
Console.WriteLine("i is not null");
}
else
{
Console.WriteLine("i is null");
}
Verkrijg de waarde van een nullable type
Gegeven volgende nullable int
int? i = 10;
Als de standaardwaarde nodig is, kunt u er een toewijzen met de operator null GetValueOrDefault
, de GetValueOrDefault
methode of controleren of de waarde HasValue
int int voor HasValue
.
int j = i ?? 0;
int j = i.GetValueOrDefault(0);
int j = i.HasValue ? i.Value : 0;
Het volgende gebruik is altijd onveilig . Als i
nul ben tijdens runtime, wordt een System.InvalidOperationException
gegenereerd. Als tijdens het ontwerp geen waarde is ingesteld, krijgt u de fout Use of unassigned local variable 'i'
.
int j = i.Value;
Een standaardwaarde krijgen van een nullable
De methode .GetValueOrDefault()
retourneert een waarde, zelfs als de eigenschap .HasValue
false is (in tegenstelling tot de eigenschap Value, die een uitzondering .HasValue
).
class Program
{
static void Main()
{
int? nullableExample = null;
int result = nullableExample.GetValueOrDefault();
Console.WriteLine(result); // will output the default value for int - 0
int secondResult = nullableExample.GetValueOrDefault(1);
Console.WriteLine(secondResult) // will output our specified default - 1
int thirdResult = nullableExample ?? 1;
Console.WriteLine(secondResult) // same as the GetValueOrDefault but a bit shorter
}
}
Output:
0
1
Controleer of een parameter van het generieke type een nullable type is
public bool IsTypeNullable<T>()
{
return Nullable.GetUnderlyingType( typeof(T) )!=null;
}
Standaardwaarde van nulbare typen is nul
public class NullableTypesExample
{
static int? _testValue;
public static void Main()
{
if(_testValue == null)
Console.WriteLine("null");
else
Console.WriteLine(_testValue.ToString());
}
}
Output:
nul
Effectief gebruik van onderliggende Nullable argument
Elk nullable type is een generiek type. En elk nulbaar type is een waardetype .
Er zijn enkele trucs die het mogelijk maken om het resultaat van de Nullable.GetUnderlyingType- methode effectief te gebruiken bij het maken van code met betrekking tot reflectie / het genereren van code:
public static class TypesHelper {
public static bool IsNullable(this Type type) {
Type underlyingType;
return IsNullable(type, out underlyingType);
}
public static bool IsNullable(this Type type, out Type underlyingType) {
underlyingType = Nullable.GetUnderlyingType(type);
return underlyingType != null;
}
public static Type GetNullable(Type type) {
Type underlyingType;
return IsNullable(type, out underlyingType) ? type : NullableTypesCache.Get(type);
}
public static bool IsExactOrNullable(this Type type, Func<Type, bool> predicate) {
Type underlyingType;
if(IsNullable(type, out underlyingType))
return IsExactOrNullable(underlyingType, predicate);
return predicate(type);
}
public static bool IsExactOrNullable<T>(this Type type)
where T : struct {
return IsExactOrNullable(type, t => Equals(t, typeof(T)));
}
}
Het gebruik:
Type type = typeof(int).GetNullable();
Console.WriteLine(type.ToString());
if(type.IsNullable())
Console.WriteLine("Type is nullable.");
Type underlyingType;
if(type.IsNullable(out underlyingType))
Console.WriteLine("The underlying type is " + underlyingType.Name + ".");
if(type.IsExactOrNullable<int>())
Console.WriteLine("Type is either exact or nullable Int32.");
if(!type.IsExactOrNullable(t => t.IsEnum))
Console.WriteLine("Type is neither exact nor nullable enum.");
Output:
System.Nullable`1[System.Int32]
Type is nullable.
The underlying type is Int32.
Type is either exact or nullable Int32.
Type is neither exact nor nullable enum.
PS. De NullableTypesCache
is als volgt gedefinieerd:
static class NullableTypesCache {
readonly static ConcurrentDictionary<Type, Type> cache = new ConcurrentDictionary<Type, Type>();
static NullableTypesCache() {
cache.TryAdd(typeof(byte), typeof(Nullable<byte>));
cache.TryAdd(typeof(short), typeof(Nullable<short>));
cache.TryAdd(typeof(int), typeof(Nullable<int>));
cache.TryAdd(typeof(long), typeof(Nullable<long>));
cache.TryAdd(typeof(float), typeof(Nullable<float>));
cache.TryAdd(typeof(double), typeof(Nullable<double>));
cache.TryAdd(typeof(decimal), typeof(Nullable<decimal>));
cache.TryAdd(typeof(sbyte), typeof(Nullable<sbyte>));
cache.TryAdd(typeof(ushort), typeof(Nullable<ushort>));
cache.TryAdd(typeof(uint), typeof(Nullable<uint>));
cache.TryAdd(typeof(ulong), typeof(Nullable<ulong>));
//...
}
readonly static Type NullableBase = typeof(Nullable<>);
internal static Type Get(Type type) {
// Try to avoid the expensive MakeGenericType method call
return cache.GetOrAdd(type, t => NullableBase.MakeGenericType(t));
}
}