Null-Coalescing Operator (??)
คืนค่า Left Operand ถ้าไม่ใช่ Null มิฉะนั้นคืนค่า Right Operand
result = left ?? right;
// เทียบเท่า:
result = (left != null) ? left : right;
คุณสมบัติ
- Short-circuit: ถ้า Left ไม่ Null → ไม่ Evaluate Right
- ทำงานกับ Nullable Value Types (
int?,DateTime?) และ Reference Types - Right Operand ต้อง Implicitly Convertible เป็น Type ของ Left
- Associative:
a ?? b ?? c=(a ?? b) ?? c(คืนค่าแรกที่ไม่ Null)
ตัวอย่างพื้นฐาน
using System;
class Program
{
static void Main()
{
// Nullable Value Type
int? value1 = null;
int value2 = value1 ?? 99; // 99
Console.WriteLine($"Value2: {value2}");
// Reference Type
string testString = "Null Coalescing";
string result = testString ?? "Original is null";
Console.WriteLine($"Result: {result}"); // Null Coalescing
// Chain
string? s1 = null;
string? s2 = null;
string s3 = "Third";
string result2 = s1 ?? s2 ?? s3 ?? "Default";
Console.WriteLine(result2); // Third
Console.ReadLine();
}
}
Output
Value2: 99 Result: Null Coalescing Third
Null-Coalescing Assignment (??=) - C# 8.0+
Assign เฉพาะตอน Left เป็น Null
string? name = null;
name ??= "Default Name"; // Assign เฉพาะตอน null
Console.WriteLine(name); // Default Name
name ??= "Another"; // ไม่ Assign เพราะ name ไม่ null แล้ว
Console.WriteLine(name); // Default Name
Use Cases จริง
1. Default Value สำหรับ Nullable
// แทน
string displayName = user.Name != null ? user.Name : "Anonymous";
// ใช้
string displayName = user.Name ?? "Anonymous";
2. Lazy Initialization
private List<string> _cache;
public List<string> Cache => _cache ??= new List<string>();
3. Fallback Chain
var config = userConfig ?? systemConfig ?? defaultConfig ?? throw new InvalidOperationException("No config");
4. กับ Nullable Reference Types (C# 8+)
#nullable enable
string? maybeNull = GetString();
string notNull = maybeNull ?? "Fallback"; // notNull เป็น string (Non-nullable)
#nullable restore
?? vs ?: (Ternary) vs ?. (Null-Conditional)
| Operator | Name | ใช้เมื่อไหร่ |
|---|---|---|
?? | Null-Coalescing | Default Value เมื่อ Null |
?: | Ternary/Conditional | Condition ใดๆ (ไม่ใช่แค่ Null) |
?. | Null-Conditional | Access Member เมื่อ Object ไม่ Null |
??= | Null-Coalescing Assignment | Assign เมื่อ Null (Lazy Init) |
ร่วมกันใช้ได้
// Safe Navigation + Default
string name = person?.Address?.City ?? "Unknown City";
// Lazy Init + Thread Safety (Simple)
private volatile List<string> _items;
public List<string> Items => _items ??= new List<string>();
ข้อควรระวัง
- Left Operand ต้องเป็น Nullable Type (Value Type ต้องเป็น
T?) - Reference Type ใช้ได้เลย (Nullable By Default)
- ไม่ทำงานกับ Non-Nullable Value Type (
intต้องเป็นint?)