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

Lợi ích của từ khóa readonly cho field trong C#

readonly cho phép gán giá trị field tại declaration hoặc trong constructor. Khác với const (compile-time constant), readonly là runtime constant.

4 Context sử dụng readonly

ContextVí dụMô tả
Field declarationreadonly int _maxSize = 100;Gán ở khai báo hoặc constructor
readonly structreadonly struct Point { ... }Struct bất biến (immutable), tất cả field readonly
readonly memberpublic readonly int GetX() => _x;Method không sửa state (C# 8.0+)
ref readonly returnpublic ref readonly int GetRef() => ref _x;Trả reference không cho sửa (C# 7.2+)

Ví dụ: Field readonly


public class Person
{
    // Gán tại declaration
    private readonly string _createdAt = DateTime.UtcNow.ToString("O");
    
    // Gán trong constructor
    private readonly Guid _id;
    public string Name { get; set; }

    public Person(string name)
    {
        _id = Guid.NewGuid(); // Chỉ gán được ở đây
        Name = name;
    }
    
    // Không thể gán _id, _createdAt ở method khác
    // public void Reset() => _id = Guid.NewGuid(); // COMPILE ERROR
}

Ví dụ: readonly struct (C# 7.2+)


// Tất cả field tự động readonly, method không thể mutate
public readonly struct Point3D
{
    public double X { get; }
    public double Y { get; }
    public double Z { get; }

    public Point3D(double x, double y, double z) => (X, Y, Z) = (x, y, z);
    
    public readonly double DistanceFromOrigin() => Math.Sqrt(X*X + Y*Y + Z*Z);
    // Không thể có method non-readonly
}

Lợi ích chính

  1. Thread Safety: Immutable data an toàn cho multi-threading.
  2. Compiler Enforcement: Ngăn gán giá trị ngoài constructor (field) hoặc mutate state (struct/method).
  3. Intent Clarity: Dễ hiểu code: field này không thay đổi sau khởi tạo.
  4. Optimization: JIT/Runtime có thể tối ưu hóa cho readonly struct (pass by ref readonly).
  5. Defensive Copy: Tránh defensive copy khi trả về struct lớn (với ref readonly return).

readonly vs const

Đặc điểmconstreadonly
Thời điểm gánCompile-timeRuntime (constructor)
Kiểu dữ liệuPrimitive, string, enum, nullBất kỳ kiểu nào
StaticLuôn static (implicit)Instance hoặc static
Giá trịCố định suốt đời chương trìnhCó thể khác nhau per instance
VersioningRủi ro (nhúng vào caller assembly)An toàn (đọc từ field tại runtime)

Best Practice

  • Dùng readonly cho field không thay đổi sau ctor.
  • Dùng readonly struct cho struct đại diện giá trị bất biến (Point, Vector, DateRange...).
  • Dùng readonly cho method không mutate state.
  • Dùng ref readonly return cho struct lớn readonly.
  • Tránh const cho giá trị có thể thay đổi giữa các version (connection string, config...).