Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Cách gán giá trị mặc định cho Auto-Property trong C#

Tiến hóa qua các phiên bản C#

Phiên bảnCách gán default value
C# 1.0 - 5.0Chỉ trong constructor
C# 6.0+Property initializer (inline)
C# 9.0+Init-only properties + with expression
C# 12+Primary constructors

C# 5.0 và trước: Constructor


public class Demo 
{
    public string FirstName { get; set; }
    public int Age { get; set; }
    
    public Demo() 
    {
        FirstName = "DefaultName";
        Age = 18;
    }
}

C# 6.0+: Property Initializer (Inline)


public class Demo 
{
    // Gán giá trị trực tiếp tại property
    public string FirstName { get; set; } = "DefaultName";
    public int Age { get; set; } = 18;
    public List Tags { get; set; } = new List();
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}

// Sử dụng
var d = new Demo();
Console.WriteLine(d.FirstName); // DefaultName
Console.WriteLine(d.Age);       // 18

C# 9.0+: Init-only Properties (Immutable)


public class Person 
{
    // Chỉ set được lúc khởi tạo (object initializer)
    public string FirstName { get; init; } = "Default";
    public string LastName { get; init; } = "User";
    public int Age { get; init; } = 18;
}

// Sử dụng
var p = new Person { FirstName = "John", Age = 25 };
// p.FirstName = "Jane"; // ❌ Compile error: init-only

// With-expression (C# 9+) - tạo copy với thay đổi
var p2 = p with { Age = 26 }; // p không đổi, p2 mới với Age=26

C# 12+: Primary Constructors


// Parameters tự động thành fields/private properties
public class Service(string name, int timeout = 30, bool retry = true) 
{
    // name, timeout, retry dùng được trong class
    public void Run() => Console.WriteLine($"{name}: {timeout}s, retry={retry}");
    
    // Có thể expose qua property
    public string Name => name;
    public int Timeout { get; } = timeout;
    public bool Retry { get; } = retry;
}

var s = new Service("API"); // timeout=30, retry=true
var s2 = new Service("DB", 60, false);

Required Properties (C# 11+)


public class Config 
{
    // BẮT BUỘC phải cung cấp khi khởi tạo
    public required string ConnectionString { get; init; }
    public required int Port { get; init; }
    
    // Optional với default
    public int Timeout { get; init; } = 30;
}

// Sử dụng
var c = new Config 
{ 
    ConnectionString = "Server=...", 
    Port = 5432 
    // Timeout = 30 (default)
};

// ❌ Compile error nếu thiếu required
// var bad = new Config { Port = 5432 };

So sánh các cách

CáchCú phápMutable?Validation?Phiên bản
ConstructorTrong body ctorCóDễ dàngC# 1.0+
Property Initializer= valueCóKhó (chỉ const/simple)C# 6.0+
Init-only{ get; init; } = valueKhông (sau init)Trong init accessorC# 9.0+
RequiredrequiredTùy init/setCompile-time checkC# 11+
Primary ConstructorClass(params)Tùy designTrong bodyC# 12+

Best Practices

  1. C# 6+: Dùng property initializer cho default values đơn giản.
  2. Immutable data: Dùng init + required + record.
  3. Complex validation: Constructor hoặc Factory Method.
  4. Dependencies: Primary constructor (C# 12) cho DI-friendly classes.
  5. Collections: Khởi tạo = new List<T>() tránh null reference.

Ví dụ tổng hợp Modern C#


// C# 12 - Record với primary constructor, required, init
public record UserProfile(
    required string Username,
    required string Email,
    string DisplayName = "Anonymous",  // Optional với default
    int Reputation = 0,                // Optional với default
    DateTime CreatedAt = default       // Default = DateTime.MinValue
) 
{
    // Validation trong primary constructor body
    public UserProfile 
    {
        if (string.IsNullOrWhiteSpace(Username))
            throw new ArgumentException("Username required");
        if (!Email.Contains("@"))
            throw new ArgumentException("Invalid email");
    }
}

// Sử dụng
var user = new UserProfile("john_doe", "john@test.com", "John", 100);
var user2 = user with { Reputation = 150 }; // Immutable update