可為 null 的實數值型別 (c # 參考) Nullable value types (C# reference)

可為 null的實值型別 T? 代表其基礎實值型別的所有值 T ,以及一個額外的null值。A nullable value type T? represents all values of its underlying value type T and an additional null value. 例如,您可以將下列三個值的任何一個指派給 bool? 變數: truefalsenullFor example, you can assign any of the following three values to a bool? variable: true, false, or null. 基礎實值型別 T 不能是可為 null 的實值型別本身。An underlying value type T cannot be a nullable value type itself.

注意

C # 8.0 引進可為 null 的參考型別功能。C# 8.0 introduces the nullable reference types feature. 如需詳細資訊,請參閱 可為 null 的參考型別For more information, see Nullable reference types. 從 c # 2 開始可以使用可為 null 的實數值型別。The nullable value types are available beginning with C# 2.

任何可為 null 的實值型別都是泛型結構的實例 System.Nullable<T>Any nullable value type is an instance of the generic System.Nullable<T> structure. 您可以使用下列任何可交換形式的基礎類型來參考可為 null 的實數值型別 TNullable<T>T?You can refer to a nullable value type with an underlying type T in any of the following interchangeable forms: Nullable<T> or T?.

當您需要代表基礎實值型別的未定義值時,通常會使用可為 null 的實值型別。You typically use a nullable value type when you need to represent the undefined value of an underlying value type. 例如,布林值或 bool 變數只能是 truefalseFor example, a Boolean, or bool, variable can only be either true or false. 不過,在某些應用程式中,變數值不能定義或遺失。However, in some applications a variable value can be undefined or missing. 例如,資料庫欄位可能包含 truefalse ,或可能完全不包含任何值,也就是 NULLFor example, a database field may contain true or false, or it may contain no value at all, that is, NULL. bool?在該案例中,您可以使用類型。You can use the bool? type in that scenario.

宣告與指派Declaration and assignment

因為實值型別可隱含轉換成對應的可為 null 實值型別,所以您可以將值指派給可為 null 實值型別的變數,就像您針對其基礎實值型別所做的一樣。As a value type is implicitly convertible to the corresponding nullable value type, you can assign a value to a variable of a nullable value type as you would do that for its underlying value type. 您也可以指派 null 值。You can also assign the null value. 例如:For example:

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

可為 null 之實值型別的預設值代表 null ,也就是其屬性會傳回的實例 Nullable<T>.HasValue falseThe default value of a nullable value type represents null, that is, it's an instance whose Nullable<T>.HasValue property returns false.

檢查可為 null 實值型別的實例Examination of an instance of a nullable value type

從 c # 7.0 開始,您可以使用 is 運算子搭配型別模式來檢查可為 null 實值型別的實例 null ,並取出基礎型別的值:Beginning with C# 7.0, you can use the is operator with a type pattern to both examine an instance of a nullable value type for null and retrieve a value of an underlying type:

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

您一律可以使用下列唯讀屬性來檢查並取得可為 null 實值型別變數的值:You always can use the following read-only properties to examine and get a value of a nullable value type variable:

下列範例 HasValue 會使用屬性來測試變數是否包含值,然後才顯示它:The following example uses the HasValue property to test whether the variable contains a value before displaying it:

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

您也可以比較可為 null 實值型別的變數 null ,而不使用 HasValue 屬性,如下列範例所示:You can also compare a variable of a nullable value type with null instead of using the HasValue property, as the following example shows:

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

從可為 null 的實值型別轉換為基礎類型Conversion from a nullable value type to an underlying type

如果您想要將可為 null 實值型別的值指派給不可為 null 的實值型別變數,您可能需要指定要指派的值來取代 nullIf you want to assign a value of a nullable value type to a non-nullable value type variable, you might need to specify the value to be assigned in place of null. 使用null 聯合運算子 ?? 來執行該作業 (您也可以 Nullable<T>.GetValueOrDefault(T) 針對相同的目的) 使用方法:Use the null-coalescing operator ?? to do that (you can also use the Nullable<T>.GetValueOrDefault(T) method for the same purpose):

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

如果您想要使用基礎數值型別的 預設 值來取代 null ,請使用 Nullable<T>.GetValueOrDefault() 方法。If you want to use the default value of the underlying value type in place of null, use the Nullable<T>.GetValueOrDefault() method.

您也可以明確地將可為 null 的實值型別轉換為不可為 null 的型別,如下列範例所示:You can also explicitly cast a nullable value type to a non-nullable type, as the following example shows:

int? n = null;

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

在執行時間,如果可為 null 的實值型別值為 null ,明確的轉換會擲回 InvalidOperationExceptionAt run time, if the value of a nullable value type is null, the explicit cast throws an InvalidOperationException.

不可為 null 的實值型別 T 可隱含轉換成對應的可為 null 實值型別 T?A non-nullable value type T is implicitly convertible to the corresponding nullable value type T?.

提起運算子Lifted operators

對應的可為 null 實值型別也支援預先定義的一元和二元 運算子 或實數值型別所支援的任何多載運算子 T T?The predefined unary and binary operators or any overloaded operators that are supported by a value type T are also supported by the corresponding nullable value type T?. 如果一或兩個運算元都是,則這些運算子(也稱為 提升運算子null 會產生 null ; 否則,運算子會使用其運算元的包含值來計算結果。These operators, also known as lifted operators, produce null if one or both operands are null; otherwise, the operator uses the contained values of its operands to calculate the result. 例如:For example:

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

注意

針對 bool? 類型,預先定義的 &| 運算子不會遵循本節所述的規則:即使其中一個運算元為,運算子評估的結果也可以是非 null nullFor the bool? type, the predefined & and | operators don't follow the rules described in this section: the result of an operator evaluation can be non-null even if one of the operands is null. 如需詳細資訊,請參閱布林邏輯運算子一文的可為 Null 的布林邏輯運算子一節。For more information, see the Nullable Boolean logical operators section of the Boolean logical operators article.

針對 比較運算子 < 、、 > <=>= ,如果其中一個或兩個運算元都是 null ,則結果為 false ; 否則會比較運算元的包含值。For the comparison operators <, >, <=, and >=, if one or both operands are null, the result is false; otherwise, the contained values of operands are compared. 請不要因為特定的比較 (例如 <=) 傳回 false,就假設相反的比較 (>) 就會傳回 trueDo not assume that because a particular comparison (for example, <=) returns false, the opposite comparison (>) returns true. 下列範例會顯示 10The following example shows that 10 is

  • 不大於或等於 nullneither greater than or equal to null
  • 或小於 nullnor less than 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

針對 相等運算子 == ,如果兩個運算元都是, null 結果就是 true ,如果只有一個運算元是,則結果為, null 否則會 false 比較運算元的包含值。For the equality operator ==, if both operands are null, the result is true, if only one of the operands is null, the result is false; otherwise, the contained values of operands are compared.

針對不 等比較運算子 != ,如果兩個運算元都是, null 結果就是 false ,如果只有一個運算元是,則結果為, null 否則會 true 比較運算元的包含值。For the inequality operator !=, if both operands are null, the result is false, if only one of the operands is null, the result is true; otherwise, the contained values of operands are compared.

如果兩個實值型別之間有 使用者定義的轉換 ,也可以在對應的可為 null 實值型別之間使用相同的轉換。If there exists a user-defined conversion between two value types, the same conversion can also be used between the corresponding nullable value types.

Box 處理和 Unbox 處理Boxing and unboxing

可為 null 的實值型別的實例 T? 會以下列方式 裝箱An instance of a nullable value type T? is boxed as follows:

  • HasValue 傳回 false,則會產生 Null 參考。If HasValue returns false, the null reference is produced.
  • 如果 HasValue 傳回 true ,則會將基礎實值型別的對應值 T 裝箱,而不是的實例 Nullable<T>If HasValue returns true, the corresponding value of the underlying value type T is boxed, not the instance of Nullable<T>.

您可以將實數值型別的已裝箱值取消封裝 T 為對應的可為 null 實值型別 T? ,如下列範例所示:You can unbox a boxed value of a value type T to the corresponding nullable value type T?, as the following example shows:

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

如何識別可為 null 的實值型別How to identify a nullable value type

下列範例示範如何判斷 System.Type 實例是否代表一個可為 null 的實值型別,也就是 System.Nullable<T> 具有指定型別參數的型別 TThe following example shows how to determine whether a System.Type instance represents a constructed nullable value type, that is, the System.Nullable<T> type with a specified type parameter 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

如範例所示,您可以使用 typeof 運算子來建立 System.Type 實例。As the example shows, you use the typeof operator to create a System.Type instance.

如果您想要判斷某個實例是否屬於可為 null 的實值型別,請不要使用 Object.GetType 方法來取得 Type 要使用上述程式碼測試的實例。If you want to determine whether an instance is of a nullable value type, don't use the Object.GetType method to get a Type instance to be tested with the preceding code. 當您 Object.GetType 在可為 null 的實值型別實例上呼叫方法時,實例就會被 封裝ObjectWhen you call the Object.GetType method on an instance of a nullable value type, the instance is boxed to Object. 當可為 null 實值型別的非 null 實例的裝箱相當於基礎類型值的裝箱時,會傳回 GetType Type 表示可為 null 實值型別之基礎型別的實例:As boxing of a non-null instance of a nullable value type is equivalent to boxing of a value of the underlying type, GetType returns a Type instance that represents the underlying type of a nullable value type:

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

此外,請勿使用「 」運算子來判斷實例是否為可為 null 的實值型別。Also, don't use the is operator to determine whether an instance is of a nullable value type. 如下列範例所示,您無法使用運算子來區別可為 null 的實值型別實例及其基礎型別實例的類型 isAs the following example shows, you cannot distinguish types of a nullable value type instance and its underlying type instance with the is operator:

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?

您可以使用下列範例中所示的程式碼,判斷實例是否為可為 null 的實值型別:You can use the code presented in the following example to determine whether an instance is of a nullable value type:

int? a = 14;
Console.WriteLine(IsOfNullableType(a));  // output: True

int b = 17;
Console.WriteLine(IsOfNullableType(b));  // output: False

bool IsOfNullableType<T>(T o)
{
    var type = typeof(T);
    return Nullable.GetUnderlyingType(type) != null;
}

注意

可為 null 的參考型別案例中,本節所述的方法不適用。The methods described in this section are not applicable in the case of nullable reference types.

C# 語言規格C# language specification

如需詳細資訊,請參閱 C# 語言規格的下列幾節:For more information, see the following sections of the C# language specification:

另請參閱See also