Sử dụng ref parameters hoặc out parameters
Để hiểu được ref parameters và out parameters là gì thì trước tiên chúng ta cùng nhắc lại kiến thức một chút về truyền tham trị và truyền tham chiếu.
- Truyền tham trị: một bản sao của biến sẽ được tạo ra, sao chép giá trị của biến, truyền biến đã được sao chép này vào hàm, dù có thực hiện bao nhiêu phép tính toán cũng không ảnh hưởng đến biến gốc
- Truyền tham chiếu: truyền ngay địa chỉ của biến được lưu trên bộ nhớ vào hàm (hay hiểu cách khác là truyền chính biến đó vào hàm) khi thực hiện tính toán thì giá trị biến này thay đổi theo. Ref và out là hai từ khóa dùng để truyền tham chiếu vào hàm. Chúng là hai từ khóa khá phổ biến và hữu ích trong lập trình C# nhưng cũng dễ gây hiểu nhầm vì có chức năng tương tự nhau.
Ví dụ với ref
private static void fun(ref int x, ref int y) { x = 1; y = 2; } public static void Main() { int x = 0; int y = 0; fun(ref x, ref y); Console.WriteLine("x = {0}, y = {1}", x, y); }
- Kết quả khi chạy chương trình
x = 1, y = 2
- Đối với ref thì biến truyền vào phải được khởi tạo giá trị trước khi truyền vào hàm.
Ví dụ với out
private static void fun(out int x, out int y) { x = 1; y = 2; } public static void Main() { int x; int y; fun(out x, out y); Console.WriteLine("x = {0}, y = {1}", x, y); }
- Đối với out thì biến truyền vào không cần khởi tạo giá trị trước khi truyền vào hàm.
Sử dụng Tuple class
- Tuple là một cấu trúc dữ liệu cho phép bạn dễ dàng đóng gói nhiều giá trị trong một đối tượng. Các bộ giá trị thường được sử dụng để trả về nhiều giá trị từ một phương thức.
- Các bạn có thể tìm hiểu thêm về Tuple tại đây
Ví dụ về Tuple
private static Tuple<int, int> fun() { return Tuple.Create(1, 2); } public static void Main() { Tuple<int, int> tuple = fun(); Console.WriteLine("x = {0}, y = {1}", tuple.Item1, tuple.Item2); }
- Kêt quả
x = 1, y = 2
Sử dụng ValueTuple có từ C# 7
- ValueTuple được giới thiệu trong .NET Framework 4.7, là các loại bộ giá trị để cung cấp việc triển khai thời gian chạy của các bộ giá trị trong C #. Giống như các lớp tuple, nó có thể được sử dụng để trả về nhiều giá trị từ một phương thức theo cách hiệu quả hơn.
Ví dụ về ValueTuple
public static void Main() { var fruits = GetFruits(); Console.WriteLine($"Fruit Id: {fruits.Item1}, Name: {fruits.Item2}, Size: {fruits.Item3}"); Console.ReadLine(); } static (int, string, string) GetFruits() { return (Id: 1, FruitName: "Apple", Size: "Big"); }
- Kết quả
Fruit Id: 1, Name: Apple, Size: Big
Sử dụng Class/Struct Type
Trả về một đối tượng thuộc Class/Struct là một cách khá phổ biến để trả về nhiều giá trị từ một hàm. Ở đây hàm sẽ trả về một đối tượng của một Class/Struc có thể đóng gói thêm n số thuộc tính bên trong chúng.
Ví dụ về Class/Struct Type
private struct Pair { public int x; public int y; } private static Pair fun() { return new Pair { x = 1, y = 2 }; } public static void Main() { Pair pair = fun(); Console.WriteLine("x = {0}, y = {1}", pair.x, pair.y); }
- Kêt quả
x = 1, y = 2
Tổng kết
- Như vậy là mk vừa giới thiệu cho các bạn một vài cách để trả về nhiều giá trị từ một hàm.
- Tùy từng nhu cầu sử dụng, dự án mà chúng ta có thể sử dụng một trong các cách trên.
- Mỗi cách đều có ưu điểm và hạn chế. Hi vọng các bạn có thể sử dụng chúng đúng với mục đích của mk