Typer av null-värden (C#-referens)

En nullbar värdetypT? representerar alla värden av dess underliggande värdetypT och ytterligare ett null-värde . Du kan till exempel tilldela något av följande tre värden till en bool? variabel: true, falseeller null. En underliggande värdetyp T kan inte vara en nullbar värdetyp.

Alla null-värdetyper är en instans av den allmänna System.Nullable<T> strukturen. Du kan referera till en nullbar värdetyp med en underliggande typ T i något av följande utbytbara formulär: Nullable<T> eller T?.

Du använder vanligtvis en nullbar värdetyp när du behöver representera det odefinierade värdet för en underliggande värdetyp. En boolesk variabel boolkan till exempel bara vara antingen true eller false. I vissa program kan dock ett variabelvärde vara odefinierat eller saknas. Ett databasfält kan till exempel innehålla true eller false, eller så kanske det inte innehåller något värde alls, det vill säga NULL. Du kan använda typen bool? i det scenariot.

Deklaration och tilldelning

Eftersom en värdetyp implicit kan konverteras till motsvarande null-värdetyp kan du tilldela ett värde till en variabel av en nullbar värdetyp som du skulle göra för dess underliggande värdetyp. Du kan också tilldela värdet null . Till exempel:

double? pi = 3.14;
char? letter = 'a';

int m2 = 10;
int? m = m2;

bool? flag = null;

// An array of a nullable value type:
int?[] arr = new int?[10];

Standardvärdet för en nullbar värdetyp representerar null, dvs. det är en instans vars Nullable<T>.HasValue egenskap returnerar false.

Undersökning av en instans av en nullbar värdetyp

Du kan använda operatorn is med ett typmönster för att både undersöka en instans av en nullbar värdetyp för null och hämta ett värde av en underliggande typ:

int? a = 42;
if (a is int valueOfA)
{
    Console.WriteLine($"a is {valueOfA}");
}
else
{
    Console.WriteLine("a does not have a value");
}
// Output:
// a is 42

Du kan alltid använda följande skrivskyddade egenskaper för att undersöka och hämta ett värde för en nullbar värdetypsvariabel:

I följande exempel används HasValue egenskapen för att testa om variabeln innehåller ett värde innan den visas:

int? b = 10;
if (b.HasValue)
{
    Console.WriteLine($"b is {b.Value}");
}
else
{
    Console.WriteLine("b does not have a value");
}
// Output:
// b is 10

Du kan också jämföra en variabel av en nullbar värdetyp med null i stället för att HasValue använda egenskapen, som följande exempel visar:

int? c = 7;
if (c != null)
{
    Console.WriteLine($"c is {c.Value}");
}
else
{
    Console.WriteLine("c does not have a value");
}
// Output:
// c is 7

Konvertering från en nullbar värdetyp till en underliggande typ

Om du vill tilldela ett värde av en nullbar värdetyp till en variabel av typen icke-nullbar värdetyp kan du behöva ange det värde som ska tilldelas i stället för null. Använd operatorn ?? null-coalescing för att göra det (du kan också använda Nullable<T>.GetValueOrDefault(T) metoden för samma ändamål):

int? a = 28;
int b = a ?? -1;
Console.WriteLine($"b is {b}");  // output: b is 28

int? c = null;
int d = c ?? -1;
Console.WriteLine($"d is {d}");  // output: d is -1

Om du vill använda standardvärdet för den underliggande värdetypen i stället för nullanvänder du Nullable<T>.GetValueOrDefault() metoden .

Du kan också uttryckligen omvandla en nullbar värdetyp till en icke-nullbar typ, vilket visas i följande exempel:

int? n = null;

//int m1 = n;    // Doesn't compile
int n2 = (int)n; // Compiles, but throws an exception if n is null

Vid körningen, om värdet för en nullbar värdetyp är null, genererar den explicita casten en InvalidOperationException.

En värdetyp som T inte kan nollföras kan implicit konverteras till motsvarande nullbara värdetyp T?.

Upplyfta operatorer

Fördefinierade odefinierade och binära operatorer eller överlagrade operatorer som stöds av en värdetyp T stöds också av motsvarande null-värdetyp T?. Dessa operatorer, även kallade lyftoperatorer, producerar null om en eller båda operanderna är null. Annars använder operatorn de inneslutna värdena för sina operander för att beräkna resultatet. Till exempel:

int? a = 10;
int? b = null;
int? c = 10;

a++;        // a is 11
a = a * c;  // a is 110
a = a + b;  // a is null

Kommentar

bool? För typen följer de fördefinierade & operatorerna | inte de regler som beskrivs i det här avsnittet: resultatet av en operatorutvärdering kan vara icke-null även om någon av operanderna är null. Mer information finns i avsnittet Booleska logiska operatorer som kan ogiltigförklaras i artikeln Booleska logiska operatorer .

För jämförelseoperatorerna< , >, <=och >=, om en eller båda operanderna är null, är falseresultatet ; annars jämförs de inneslutna värdena för operander. Anta inte att eftersom en viss jämförelse (till exempel <=) returnerar returnerar falsetrueden motsatta jämförelsen (>). Följande exempel visar att 10 är

  • varken större än eller lika med null
  • eller mindre än null
int? a = 10;
Console.WriteLine($"{a} >= null is {a >= null}");
Console.WriteLine($"{a} < null is {a < null}");
Console.WriteLine($"{a} == null is {a == null}");
// Output:
// 10 >= null is False
// 10 < null is False
// 10 == null is False

int? b = null;
int? c = null;
Console.WriteLine($"null >= null is {b >= c}");
Console.WriteLine($"null == null is {b == c}");
// Output:
// null >= null is False
// null == null is True

För likhetsoperatorn==, om båda operanderna är null, är trueresultatet , om bara en av operanderna är null, resultatet är false; annars jämförs de inneslutna värdena för operander.

Om båda operanderna är nullför olikhetsoperatorn!= är falseresultatet , om bara en av operanderna är null, resultatet är true, annars jämförs de inneslutna värdena för operander.

Om det finns en användardefinierad konvertering mellan två värdetyper kan samma konvertering också användas mellan motsvarande nullbara värdetyper.

Boxning och avboxning

En instans av en nullbar värdetyp T?boxas på följande sätt:

  • Om HasValue returnerar falseskapas null-referensen.
  • Om HasValue returnerar trueboxas motsvarande värde för den underliggande värdetypen T , inte instansen av Nullable<T>.

Du kan ta bort ett rutat värde av en värdetyp T till motsvarande nullbar värdetyp T?, som följande exempel visar:

int a = 41;
object aBoxed = a;
int? aNullable = (int?)aBoxed;
Console.WriteLine($"Value of aNullable: {aNullable}");

object aNullableBoxed = aNullable;
if (aNullableBoxed is int valueOfA)
{
    Console.WriteLine($"aNullableBoxed is boxed int: {valueOfA}");
}
// Output:
// Value of aNullable: 41
// aNullableBoxed is boxed int: 41

Så här identifierar du en värdetyp som kan ogiltigförklaras

I följande exempel visas hur du avgör om en System.Type instans representerar en konstruerad nullbar värdetyp, System.Nullable<T> det vill säga typen med en angiven typparameter T:

Console.WriteLine($"int? is {(IsNullable(typeof(int?)) ? "nullable" : "non nullable")} value type");
Console.WriteLine($"int is {(IsNullable(typeof(int)) ? "nullable" : "non-nullable")} value type");

bool IsNullable(Type type) => Nullable.GetUnderlyingType(type) != null;

// Output:
// int? is nullable value type
// int is non-nullable value type

Som exemplet visar använder du typ av operator för att skapa en System.Type instans.

Om du vill avgöra om en instans har en värdetyp som kan vara null ska du inte använda Object.GetType metoden för att få en Type instans att testas med föregående kod. När du anropar Object.GetType metoden på en instans av en nullbar värdetyp, boxas instansen till Object. Eftersom boxning av en icke-null-instans av en nullbar värdetyp motsvarar boxning av ett värde av den underliggande typen, GetType returnerar en Type instans som representerar den underliggande typen av en nullbar värdetyp:

int? a = 17;
Type typeOfA = a.GetType();
Console.WriteLine(typeOfA.FullName);
// Output:
// System.Int32

Använd inte heller is-operatorn för att avgöra om en instans är av en nullbar värdetyp. Som i följande exempel visas kan du inte skilja mellan typer av en nullbar värdetypsinstans och dess underliggande typinstans med operatorn is :

int? a = 14;
if (a is int)
{
    Console.WriteLine("int? instance is compatible with int");
}

int b = 17;
if (b is int?)
{
    Console.WriteLine("int instance is compatible with int?");
}
// Output:
// int? instance is compatible with int
// int instance is compatible with int?

Använd Nullable.GetUnderlyingType i stället från det första exemplet och typ av operator för att kontrollera om en instans har en värdetyp som kan vara null.

Kommentar

De metoder som beskrivs i det här avsnittet gäller inte för referenstyper som kan upphävas.

Språkspecifikation för C#

Mer information finns i följande avsnitt i C#-språkspecifikationen:

Se även