Typy wartości dopuszczalnych wartości (odwołanie w C#)

TypT? wartości dopuszczanej do wartości null reprezentuje wszystkie wartości bazowego typuT wartości i dodatkową wartość null. Można na przykład przypisać dowolną z następujących trzech wartości do zmiennejbool?: true, lub falsenull. Typ wartości T bazowej nie może być typem wartości dopuszczanej do wartości null.

Każdy typ wartości dopuszczanej do wartości null jest wystąpieniem struktury ogólnej System.Nullable<T> . Można odwołać się do typu wartości dopuszczanej wartości null z typem T bazowym w dowolnej z następujących zamiennych form: Nullable<T> lub T?.

Zazwyczaj używasz typu wartości dopuszczającego wartość null, gdy musisz reprezentować niezdefiniowaną wartość bazowego typu wartości. Na przykład zmienna logiczna lub bool, może mieć wartość lub truefalse. Jednak w niektórych aplikacjach wartość zmiennej może być niezdefiniowana lub brakująca. Na przykład pole bazy danych może zawierać true wartość lub false, lub może nie zawierać żadnej wartości, czyli NULL. Możesz użyć typu w tym scenariuszu bool? .

Deklaracja i przypisanie

Ponieważ typ wartości jest niejawnie konwertowany na odpowiadający typ wartości dopuszczających wartość null, można przypisać wartość do zmiennej typu wartości dopuszczanej do wartości null, tak jak w przypadku jego bazowego typu wartości. Możesz również przypisać null wartość. Na przykład:

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];

Wartość domyślna typu wartości dopuszczanej do wartości null reprezentuje null, czyli jest to wystąpienie, którego Nullable<T>.HasValue właściwość zwraca wartość false.

Badanie wystąpienia typu wartości dopuszczanej do wartości null

Możesz użyć is operatora z wzorcem typu, aby zbadać wystąpienie typu null wartości dopuszczanej do wartości null i pobrać wartość typu bazowego:

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

Zawsze możesz użyć następujących właściwości tylko do odczytu, aby sprawdzić i uzyskać wartość zmiennej typu wartości dopuszczanej do wartości null:

W poniższym przykładzie użyto HasValue właściwości , aby sprawdzić, czy zmienna zawiera wartość przed jej wyświetleniem:

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

Można również porównać zmienną typu wartości dopuszczanej z wartością null null zamiast używać HasValue właściwości, jak pokazano w poniższym przykładzie:

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

Konwersja z typu wartości dopuszczanej do wartości null do typu bazowego

Jeśli chcesz przypisać wartość typu wartości dopuszczanej do wartości null do zmiennej typu wartości innej niż null, może być konieczne określenie wartości, która ma zostać przypisana zamiast null. Użyj operatora ?? łączenia wartości null, aby to zrobić (możesz również użyć Nullable<T>.GetValueOrDefault(T) metody w tym samym celu):

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

Jeśli chcesz użyć wartości domyślnej bazowego typu wartości zamiast null, użyj Nullable<T>.GetValueOrDefault() metody .

Można również jawnie rzutować typ wartości dopuszczanej do wartości null do typu innego niż null, jak pokazano w poniższym przykładzie:

int? n = null;

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

W czasie wykonywania, jeśli wartość typu wartości dopuszczanej do wartości null to null, jawne rzutowanie zgłasza wartość InvalidOperationException.

Typ T wartości innej niż null jest niejawnie konwertowany na odpowiadający typ T?wartości dopuszczanej do wartości null.

Operatory zniesione

Wstępnie zdefiniowane operatory jednoargumentowe i binarne lub wszelkie przeciążone operatory obsługiwane przez typ T wartości są również obsługiwane przez odpowiedni typ T?wartości dopuszczających wartość null. Te operatory, znane również jako operatory zniesione, generują null , jeśli jeden lub oba operandy są null; w przeciwnym razie operator używa zawartych wartości jego operandów do obliczenia wyniku. Na przykład:

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

Uwaga

bool? Dla typu wstępnie zdefiniowane & operatory i | nie są zgodne z regułami opisanymi w tej sekcji: wynik oceny operatora może być inny niż null, nawet jeśli jeden z operandów to null. Aby uzyskać więcej informacji, zobacz sekcję Operatory logiczne dopuszczane do wartości null w artykule Logiczne operatory logiczne.

W przypadku operatorów< porównania, >, <=i >=, jeśli jeden lub oba operandy to null, wynikiem jest false; w przeciwnym razie zawarte wartości operandów są porównywane. Nie zakładaj, że ponieważ określone porównanie (na przykład <=) zwraca falsewartość , odwrotne porównanie (>) zwraca wartość true. W poniższym przykładzie pokazano, że 10 to

  • ani większe niż, ani równe null
  • lub mniej niż 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

W przypadku operatora== równości, jeśli oba operandy są null, wynikiem jest , jeśli tylko jeden z operandów to truenull, wynik to false; w przeciwnym razie zawarte wartości operandów są porównywane.

W przypadku operatora!= nierówności, jeśli oba operandy są null, wynikiem jest , jeśli tylko jeden z operandów to falsenull, wynikiem jest true; w przeciwnym razie zawarte wartości operandów są porównywane.

Jeśli istnieje konwersja zdefiniowana przez użytkownika między dwoma typami wartości, można również użyć tej samej konwersji między odpowiadającymi typami wartości dopuszczania wartości null.

Boxing and unboxing (Boks i rozpakowywanie)

Wystąpienie typu T? wartości dopuszczanej do wartości null jest w następujący sposób:

  • Jeśli HasValue zwraca falsewartość , zostanie wygenerowane odwołanie o wartości null.
  • Jeśli HasValue zwraca truewartość , odpowiednia wartość typu T wartości bazowej jest w polu, a nie wystąpienie klasy Nullable<T>.

Możesz rozpakować pole typu wartości typu wartości T do odpowiedniego typu T?wartości dopuszczanej do wartości null, jak pokazano w poniższym przykładzie:

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

Jak zidentyfikować typ wartości dopuszczanej do wartości null

W poniższym przykładzie pokazano, jak określić, czy System.Type wystąpienie reprezentuje skonstruowany typ wartości dopuszczający wartość null, System.Nullable<T> czyli typ z określonym parametrem Ttypu :

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

Jak pokazano w przykładzie, użyj operatora typeof , aby utworzyć System.Type wystąpienie.

Jeśli chcesz określić, czy wystąpienie ma typ wartości dopuszczającej wartość null, nie używaj Object.GetType metody w celu Type przetestowania wystąpienia z poprzednim kodem. Po wywołaniu Object.GetType metody w wystąpieniu typu wartości dopuszczanej wartości null wystąpienie jest w poluObject. Jako że boxing wystąpienia wartości innej niż null typu wartości dopuszczającej wartość null jest odpowiednikiem pola wartości typu bazowego, GetType zwraca Type wystąpienie reprezentujące podstawowy typ wartości dopuszczającej wartość null:

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

Ponadto nie używaj operatora is , aby określić, czy wystąpienie ma typ wartości dopuszczalnej wartości null. Jak pokazano w poniższym przykładzie, nie można odróżnić typów wystąpienia typu wartości null i jego wystąpienia typu bazowego z operatorem 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?

Zamiast tego użyj Nullable.GetUnderlyingType operatora z pierwszego przykładu i typeof , aby sprawdzić, czy wystąpienie ma typ wartości dopuszczalnej wartości null.

Uwaga

Metody opisane w tej sekcji nie mają zastosowania w przypadku typów odwołań dopuszczanych do wartości null.

specyfikacja języka C#

Aby uzyskać więcej informacji, zobacz następujące sekcje specyfikacji języka C#:

Zobacz też