Nullable Types & Null Safety

লেসন ১৪ / ৫০

Nullable Value Types

// Value type — by default non-null
int x = null;        // ❌ Error

int? y = null;       // ✅ Nullable<int>
int? age = 25;

if (age.HasValue) Console.WriteLine(age.Value);
int actual = age ?? 0;          // null-coalescing

Nullable Reference Types (C# 8+) ⭐

// .csproj
<Nullable>enable</Nullable>

// এখন:
string name = null;        // ⚠️ Warning
string? maybeName = null;  // ✅ OK

void Print(string s) => Console.WriteLine(s);
Print(maybeName);          // ⚠️ Warning - might be null

Null-Conditional Operator (?.)

string name = user?.Profile?.FullName;
// user null হলে name = null, NullReferenceException নেই

int? len = name?.Length;

// Method
user?.Save();    // user null হলে কিছু হবে না

// Indexer
var first = list?[0];

Null-Coalescing Operator (??)

string name = user?.Name ?? "Unknown";

// ??= (compound assign)
options ??= new Options();    // null হলে set

Null-Forgiving Operator (!)

string? maybe = GetName();
int len = maybe!.Length;    // আমি জানি null না, suppress warning

// সাবধানে ব্যবহার — runtime এ null হলে crash

is null / is not null

if (user is null) return;
if (user is not null) Process(user);

ArgumentNullException Helper

// C# 11+
public void Process(string name) {
    ArgumentNullException.ThrowIfNull(name);
    // ...
}

// Older
public void Process(string name) {
    if (name == null) throw new ArgumentNullException(nameof(name));
}

Complete Example

public class UserService {
    private readonly Db _db;

    public UserService(Db db) {
        _db = db ?? throw new ArgumentNullException(nameof(db));
    }

    public string GetUserCity(int id) {
        var user = _db.Users.Find(id);
        return user?.Address?.City ?? "Unknown";
    }
}