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