Typy wartości dopuszczalnych wartości (odwołanie w C#)
Typ T?
wartości dopuszczanej do wartości null reprezentuje wszystkie wartości bazowego typu T
wartości i dodatkową wartość null. Można na przykład przypisać dowolną z następujących trzech wartości do zmiennejbool?
: true
, lub false
null
. 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 true
false
. 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:
Nullable<T>.HasValue wskazuje, czy wystąpienie typu wartości dopuszczanej do wartości null ma wartość swojego typu bazowego.
Nullable<T>.Value pobiera wartość typu bazowego, jeśli HasValue ma wartość
true
. Jeśli HasValue parametr mafalse
wartość , Value właściwość zgłasza wartość InvalidOperationException.
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 false
wartość , 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
Dla operatora ==
równości , jeśli oba operandy są null
, wynikiem jest , jeśli tylko jeden z operandów to true
null
, 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 false
null
, 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
false
wartość , zostanie wygenerowane odwołanie o wartości null. - Jeśli HasValue zwraca
true
wartość , odpowiednia wartość typuT
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 T
typu :
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 polu Object. 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#:
- Typy dopuszczane do wartości null
- Operatory zniesione
- Niejawne konwersje dopuszczane do wartości null
- Jawne konwersje dopuszczane do wartości null
- Operatory konwersji zniesionej