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));
}
}