From: 011netservice@gmail.com
Date: 2025-05-03
Subject: null.txt
https://svc.011.idv.tw/CodeHelper/cs/KeyWord/null.txt
歡迎來信交流, 訂購軟體需求.
#### CodeHelper null 摘要
CodeHelper null! ,null-forgiving operator, 通知編譯器確認為"non-null"型別, 2025-05-02
從 C# 8.0 開始支援 null!
null! 代表通知編譯器確認為"non-null"型別.
The post-fix ! operator is called the null-forgiving operator.
The postfix ! operator has no runtime effect - it evaluates to the result of the underlying expression.
Its only role is to change the null state of the expression, and to limit warnings given on its use.
https://stackoverflow.com/questions/54724304/what-does-null-statement-mean
Basically, null! applies the ! operator to the value null. This overrides the nullability of the value null to non-nullable,
telling the compiler that null is a "non-null" type.
support since C# 8.0.
Typical usage
Assuming this definition:
class Person
{
// Not every person has a middle name. We express "no middle name" as "null"
public string? MiddleName;
}
The usage would be:
void LogPerson(Person person)
{
Console.WriteLine(person.MiddleName.Length); // WARNING: may be null
Console.WriteLine(person.MiddleName!.Length); // No warning
}
CodeHelper Null, CodeHelper attribute, CodeHelper MaybeNullWhen, CodeHelper NotNullWhen
範例:
using System.Diagnostics.CodeAnalysis; // 必須引用.
public static bool ZIsDBNull([NotNullWhen(true)] object? PObject)
=> Convert.IsDBNull(PObject);
public static bool ZTryParseVersion([NotNullWhen(true)] this string? PInput, [NotNullWhen(true)] out Version? PResult)
=> Version.TryParse(PInput, out PResult);
[MaybeNullWhen(false)] 後面的參數不用加 ?, 但是在使用時必須加?, 如下例
bool CheckRegistration(int PConnectNo, C_HelloReply PC_HelloReply, [MaybeNullWhen(false)] out ZRegistration PRegistration)
if (CheckRegistration(PConnectNo, Receive1, out ZRegistration? Registration1))
#### Nullable reference types: Warning CS8632...
若碰到 Warning CS8632 The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
這是因為 預設 Nullable References 語法和編譯警告都是關閉的(disabled), 但是從 .NET 6 開始, 預設已改為 enabled.
By default, nullable annotation and warning contexts are disabled.
That means that your existing code compiles without changes and without generating any new warnings.
Beginning with .NET 6, new projects include the element in all project templates. enable
開啟 enable:
1. 整個專案開啟:
例如:
netstandard2.0;net6.0
enable
2. 個別區塊中開啟
CodeHelper null, #nullable enable, 程式碼中區塊開啟 nullable
CodeHelper null, #nullable disable, 程式碼中區塊關閉 nullable
□ (int?) 是 Nullable型別, 可允許存放 null 到(原本無法存放 null 的型別)中.
int? a = null;
□ object[]? vs object?[] vs object?[]?
CodeHelper null, 1. object[]?: 整個 object[] 可為 null.
CodeHelper null, 2. object?[]: object[] 中的每個元素可為 null.
CodeHelper null, 3. object?[]?: 整個 object[] 可為 null, 每個元素也可為 null.
#### 以下舊資料確認後移到上方.
----------
20191227
摘要:
1. Null-conditional operators ?.
Null 條件運算子 ?.
Available in C# 6 and later, a null-conditional operator applies a member access, ?., or element access, ?[], operation to its operand only if that operand evaluates to non-null; otherwise, it returns null. That is,
If a evaluates to null, the result of a?.x or a?[x] is null.
If a evaluates to non-null, the result of a?.x or a?[x] is the same as the result of a.x or a[x], respectively.
若 a 為 null, 則 a?.x 為 null 或 a?.[x] 為 null.
若 a 不為 null, 則 a?.x 為 a.x 或 a?.[x] 為 a.[x].
簡稱: 若(?.前)為 null, 則不執行(?.後)的運算.
例如:
object?.Dispose()
若 ojbect 為 null, 則不執行 Dispose(), 否則 Dispose().
可取代
if (object != null)
object.Dispose();
2. null-coalescing operator ??
Null 聯合運算子 ??
The null-coalescing operator ?? returns the value of its left-hand operand if it isn't null; otherwise, it evaluates the right-hand operand and returns its result. The ?? operator doesn't evaluate its right-hand operand if the left-hand operand evaluates to non-null.
簡稱: 若(??前)為null, 則取用(??後)的結果
例如:
int? a = null;
int b = a ?? -1;
Console.WriteLine(b); // output: -1
可取代
if (a is null)
b = -1;
else
b = a;
3. null-coalescing assignment operator ??=
Null 聯合指派運算子
Available in C# 8.0 and later, the null-coalescing assignment operator ??= assigns the value of its right-hand operand to its left-hand operand only if the left-hand operand evaluates to null. The ??= operator doesn't evaluate its right-hand operand if the left-hand operand evaluates to non-null.
簡稱: 若(??=前)為null, 則指派為(??=後)的結果.
例如:
variable ??= expression;
可取代
if (variable is null)
variable = expression;
4. (int?) 是Nullable 變數, 不要跟 (Null 條件運算子 ?.) 搞混了.
5. Conditional operator ?:
條件運算元 ?:
The conditional operator ?:, also known as the ternary conditional operator, evaluates a Boolean expression and returns the result of one of the two expressions, depending on whether the Boolean expression evaluates to true or false. Beginning with C# 7.2, the conditional ref expression returns the reference to the result of one of the two expressions.
例如:
condition ? consequent: alternative
若條件 condition 成立, 則取結果 consequent, 否則取 替代 alternative
其餘慢慢看下面:
Null 條件運算子 ?. 和 ?[]
適用於 C# 6 和更新版本,Null 條件運算子只有在其運算元評估為非 Null 時,才會將成員存取 ?. 或項目存取 ?[] 作業套用至該運算元。 如果運算元評估為 null,則套用運算子的結果會是 null。 Null 條件成員存取運算子 ?. 也被稱為 Elvis 運算子。
Null 條件運算子會執行最少運算。 換句話說,如果條件式成員或項目存取作業鏈結中的一個作業傳回 null,則鏈結的其餘部分不會執行。 在下列範例中,如果 A 評估為 null,則不會評估 B;如果 A 或 B 評估為 null,則不會評估 C:
A?.B?.Do(C);
A?.B?[C];
double SumNumbers(List setsOfNumbers, int indexOfSetToSum)
{
return setsOfNumbers?[indexOfSetToSum]?.Sum() ?? double.NaN;
}
var sum1 = SumNumbers(null, 0);
Console.WriteLine(sum1); // output: NaN
var numberSets = new List
{
new[] { 1.0, 2.0, 3.0 },
null
};
var sum2 = SumNumbers(numberSets, 0);
Console.WriteLine(sum2); // output: 6
var sum3 = SumNumbers(numberSets, 1);
Console.WriteLine(sum3); // output: NaN
----------
20191227
?? 還有?= 運算子(C#參考)
如果 Null 聯合運算子 ?? 不是 null,會傳回其左方運算元的值;否則它會評估右方運算元,並傳回其結果。 如果左方運算元評估為非 Null,?? 運算子不會評估其右方運算元。
可在C# 8.0 和更新版本中使用,如果左運算元評估為null,則 null 聯合指派運算子??=會將其右運算元的值指派給其左邊的運算元。 如果左方運算元評估為非 Null,??= 運算子不會評估其右方運算元。
List numbers = null;
int? a = null;
(numbers ??= new List()).Add(5);
Console.WriteLine(string.Join(" ", numbers)); // output: 5
numbers.Add(a ??= 0);
Console.WriteLine(string.Join(" ", numbers)); // output: 5 0
Console.WriteLine(a); // output: 0
??= 運算子的左邊運算元必須是變數、屬性或索引子元素。
在C# 7.3 和更早版本中,?? 運算子的左邊運算元類型必須是參考型別或可為 null 的實數值型別。 從C# 8.0 開始,這項需求會以下列內容取代:??和??=運算子的左邊運算元類型不能是不可為 null 的實數值型別。 特別是從C# 8.0 開始,您可以使用 null 聯合運算子搭配不受限制的類型參數:
private static void Display(T a, T backup)
{
Console.WriteLine(a ?? backup);
}
Null 聯合運算子是右向關聯。 也就是表單的運算式
a ?? b ?? c
d ??= e ??= f
評估為
a ?? (b ?? c)
d ??= (e ??= f)
範例
在下列案例中,?? 和 ??= 運算子可能會很有用:
在具有null 條件運算子?. 和? []的運算式中,您可以使用 ?? 運算子來提供另一個運算式,以便在具有 null 條件運算的運算式結果為 null時進行評估:
double SumNumbers(List setsOfNumbers, int indexOfSetToSum)
{
return setsOfNumbers?[indexOfSetToSum]?.Sum() ?? double.NaN;
}
var sum = SumNumbers(null, 0);
Console.WriteLine(sum); // output: NaN
當您使用可為 null 的實數值型別,而且需要提供基礎實數值型別的值時,請使用 ?? 運算子來指定要提供的值,以防可為 null 的型別值為 null:
int? a = null;
int b = a ?? -1;
Console.WriteLine(b); // output: -1
如果可為 Null 型別的值為 null 時要使用的值為基礎實值型別的預設值,請使用 Nullable.GetValueOrDefault() 方法。
從C# 7.0 開始,您可以使用throw 運算式做為??運算子的右運算元,讓引數檢查程式碼變得更簡潔:
public string Name
{
get => name;
set => name = value ?? throw new ArgumentNullException(nameof(value), "Name cannot be null");
}
上述範例中也會示範如何使用運算式主體成員定義屬性。
從C# 8.0 開始,您可以使用??=運算子來取代表單的程式碼
if (variable is null)
{
variable = expression;
}
使用下列程式碼:
variable ??= expression;
運算子是否可多載
?? 和 ??= 的運算子無法多載。
----------
null 關鍵字是表示不參考任何物件之 Null 參考的常值。
null 是參考型別變數的預設值。
一般實值型別 (Value Type) 不可以為 null。
string s1 = null;
object o1 = null;
int? i1 = null;
// 這樣寫會exception.
//Trace.WriteLine(string.Format("string Null={0}.", s1.ToString()));
//Trace.WriteLine(string.Format("object Null={0}.", o1.ToString()));
// 這樣寫沒問題.
Trace.WriteLine(string.Format("string Null={0}.", s1));
Trace.WriteLine(string.Format("object Null={0}.", o1));
Trace.WriteLine(string.Format("int? Null.ToString()={0}.", i1.ToString()));
Trace.WriteLine(string.Format("int? Null={0}.", i1));
output:
string Null=.
object Null=.
int? Null.ToString()=.
int? Null=.
----------
class Program
{
class MyClass
{
public void MyMethod() { }
}
static void Main(string[] args)
{
// Set a breakpoint here to see that mc = null.
// However, the compiler considers it "unassigned."
// and generates a compiler error if you try to
// use the variable.
MyClass mc;
// Now the variable can be used, but...
mc = null;
// ... a method call on a null object raises
// a run-time NullReferenceException.
// Uncomment the following line to see for yourself.
// mc.MyMethod();
// Now mc has a value.
mc = new MyClass();
// You can call its method.
mc.MyMethod();
// Set mc to null again. The object it referenced
// is no longer accsessible and can now be garbage-collected.
mc = null;
// A null string is not the same as an empty string.
string s = null;
string t = String.Empty; // Logically the same as ""
// Equals applied to any null object returns false.
bool b = (t.Equals(s));
Console.WriteLine(b);
// Equality operator also returns false when one
// operand is null.
Console.WriteLine("Empty string {0} null string", s == t ? "equals": "does not equal");
// Returns true.
Console.WriteLine("null == null is {0}", null == null);
// A value type cannot be null
// int i = null; // Compiler error!
// Use a nullable value type instead:
int? i = null;
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}