C# Language
Nullable typer
Sök…
Syntax
-
Nullable<int> i = 10;
- int? j = 11;
- int? k = noll;
- Datum Tid? DateOfBirth = DateTime.Now;
- decimal? Mängd = 1,0 m;
- bool? IsAvailable = true;
- röding? Bokstav = 'a';
- (typ)? variabelnamn
Anmärkningar
Nullable typer kan representera alla värden för en underliggande typ såväl som null
.
Syntaxen T?
är kortfattad för Nullable<T>
Nullable värden är System.ValueType
objekt, så att de kan boxas och unboxas. null
för ett nollbart objekt är inte detsamma som ett null
för ett referensobjekt, det är bara en flagga.
När en nullable objektboxning konverteras null
till null
, och icke-nollvärdet konverteras till icke-nollbara underliggande typ.
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
Den andra regeln leder till korrekt, men paradoxal kod:
DateTime? dt = new DateTime(2015, 12, 11);
var o = (object)dt;
var type = o.GetType(); // is DateTime, not Nullable<DateTime>
I kort form:
DateTime? dt = new DateTime(2015, 12, 11);
var type = dt.GetType(); // is DateTime, not Nullable<DateTime>
Initierar en nullable
För null
:
Nullable<int> i = null;
Eller:
int? i = null;
Eller:
var i = (int?)null;
För icke-nollvärden:
Nullable<int> i = 0;
Eller:
int? i = 0;
Kontrollera om en nullable har ett värde
int? i = null;
if (i != null)
{
Console.WriteLine("i is not null");
}
else
{
Console.WriteLine("i is null");
}
Vilket är samma som:
if (i.HasValue)
{
Console.WriteLine("i is not null");
}
else
{
Console.WriteLine("i is null");
}
Få värdet på en nullable typ
Givet efter nullable int
int? i = 10;
Om standardvärde behövs, kan du tilldela en med hjälp av nollkoalesceringsoperatör , GetValueOrDefault
metoden eller kontrollera om nullable int HasValue
före tilldelning.
int j = i ?? 0;
int j = i.GetValueOrDefault(0);
int j = i.HasValue ? i.Value : 0;
Följande användning är alltid osäker . Om i
är noll vid körning System.InvalidOperationException
ett System.InvalidOperationException
. Vid designtid, om ett värde inte är inställt, får du ett Use of unassigned local variable 'i'
-fel.
int j = i.Value;
Få ett standardvärde från en nollstång
.GetValueOrDefault()
returnerar ett värde även om egenskapen .HasValue
är falsk (till skillnad från egenskapen Value, som kastar ett undantag).
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
}
}
Produktion:
0
1
Kontrollera om en generisk typparameter är en nullable typ
public bool IsTypeNullable<T>()
{
return Nullable.GetUnderlyingType( typeof(T) )!=null;
}
Standardvärdet för nollbara typer är noll
public class NullableTypesExample
{
static int? _testValue;
public static void Main()
{
if(_testValue == null)
Console.WriteLine("null");
else
Console.WriteLine(_testValue.ToString());
}
}
Produktion:
null
Effektiv användning av underliggande nullable argument
Varje nullable typ är en generisk typ. Och alla nollbara typer är en värdetyp .
Det finns några trick som gör det möjligt att effektivt använda resultatet av metoden Nullable.GetUnderlyingType när du skapar koder relaterade till reflektions- / kodgenereringsändamål:
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)));
}
}
Användningen:
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.");
Produktion:
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. NullableTypesCache
definieras enligt följande:
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));
}
}