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

Cách dùng từ khóa ref, out, in trong C#

Trong C#, method có tham số định nghĩa dữ liệu đầu vào. Code gọi method truyền arguments. Tham số mặc định truyền bằng giá trị (by value): tạo bản sao, thay đổi trong method không ảnh hưởng biến gốc.


int number = 8;
Increase(number);
Console.WriteLine(number); // 8

static void Increase(int num)
{
    num = num + 1;
    Console.WriteLine(num); // 9
}

Khi truyền reference type (object), C# copy reference by value. Cả 2 tham chiếu cùng object → thay đổi object bên trong method thấy được bên ngoài.


var john = new User { Name = "John", Salary = 50000 };
Promote(john);
Console.WriteLine(john.Salary); // 60000

static void Promote(User u)
{
    u.Salary += 10000;
    Console.WriteLine(u.Salary); // 60000
}

Nhưng gán lại biến tham số (u = null) không ảnh hưởng biến gốc.

1. Từ khóa ref

Truyền tham số bằng tham chiếu (by reference). Dù value type hay reference type, cả 2 cùng trỏ 1 vị trí bộ nhớ.


var john = new User { Name = "John", Salary = 50000 };
Promote(ref john);
Console.WriteLine(john?.Salary); // NullReferenceException

static void Promote(ref User u)
{
    u = null;
}

Tham số ref phải khởi tạo trước khi truyền.

2. Từ khóa out

Tương tự ref nhưng:

  • Tham số KHÔNG cần khởi tạo trước khi vào method
  • Phải khởi tạo (gán giá trị) TRƯỚC KHI RA KHỎI method

Ví dụ Hire khởi tạo object qua out:


Hire(out User john);
Console.WriteLine(john.Salary); // 50000

static void Hire(out User u)
{
    u = new User { Name = "John", Salary = 50000 };
}

Dùng out để trả về nhiều giá trị từ method:


var john = new User { Name = "John", Salary = 50000 };
bool shouldPromote = Raise(john.Salary, out double hike);
Console.WriteLine(shouldPromote); // True
Console.WriteLine($"Hike Amount = {hike}"); // 5000

static bool Raise(int salary, out double hike)
{
    hike = salary * 0.1;
    return hike < 7000;
}

3. Từ khóa in

Giống ref/out nhưng method KHÔNG THỂ sửa đổi argument. Thử sửa → lỗi compile-time.

Tiết kiệm copy bộ nhớ cho value type lớn, đồng thời ngăn chặn sửa đổi vô tình.


var point = new Coord();
Verify(point);

static void Verify(in Coord c)
{
    // Error: Cannot assign to variable 'in Coord' because it is readonly
    c = new Coord();
}

struct Coord { public int X; public int Y; }

Ví dụ tổng hợp


using System;

class Program
{
    static void Main()
    {
        int number = 8;
        Increase(number);
        Console.WriteLine(number); // 8

        var john = new User { Name = "John", Salary = 50000 };
        Promote(john);
        Console.WriteLine(john.Salary); // 60000

        Leave(john);
        Console.WriteLine(john.Salary); // 60000

        LeaveByRef(ref john);
        Console.WriteLine(john?.Salary); // null

        User dave;
        Hire(out dave);
        Console.WriteLine(dave.Salary); // 50000
    }

    static void Increase(int num) { num++; Console.WriteLine(num); } // 9
    static void Promote(User u) { u.Salary += 10000; Console.WriteLine(u.Salary); } // 60000
    static void Leave(User u) { u = null; }
    static void LeaveByRef(ref User u) { u = null; }
    static void Hire(out User u) { u = new User { Name = "John", Salary = 50000 }; }
}

class User { public string Name { get; set; } public int Salary { get; set; } }

Kết quả đầu ra

9
8
60000
60000
60000
50000