Computer >> Máy Tính >  >> Lập trình >> C#

Việc sử dụng các từ khóa ref, out và in trong C # là gì?

Trong C #, hầu hết các phương thức có thể không có hoặc nhiều tham số xác định dữ liệu phải được cung cấp cho phương thức. Bất kỳ mã nào gọi phương thức phải chuyển dữ liệu (được gọi là đối số) cho phương thức. Một phương thức khai báo các đầu vào của nó dưới dạng tham số và chúng được cung cấp bằng cách gọi mã dưới dạng đối số.

Ví dụ:hãy xem xét phương thức sau và cuộc gọi phương thức tiếp theo.

static void Greet(string greeting){
   Console.WriteLine(greeting);
}
...
Greet("Hello");

Trong ví dụ trên, lời chào là một tham số của phương thức Greet () và "Xin chào" là một đối số được truyền cho phương thức này.

Khi bạn gọi một phương thức và truyền các đối số, chúng sẽ được truyền theo giá trị, có nghĩa là một bản sao của giá trị được tạo khi truyền cho phương thức. Bất kỳ thay đổi nào được thực hiện đối với đối số bên trong phương thức không được phản ánh trên biến ban đầu.

using System;
int number = 8;
Increase(number);
Console.WriteLine(number); // prints 8
static void Increase(int num){
   num = num + 1;
   Console.WriteLine(num); // prints 9
}

Khi bạn chuyển một biến kiểu tham chiếu, chẳng hạn như một đối tượng, C # vẫn sao chép tham chiếu theo giá trị, bởi vì biến giữ tham chiếu, không phải đối tượng thực tế. Vì vậy, mặc dù một bản sao của biến tham chiếu được truyền xung quanh, cả hai đều tham chiếu đến cùng một đối tượng trong bộ nhớ. Vì vậy, bất kỳ thay đổi nào được thực hiện đối với đối tượng bởi biến bên trong phương thức đều hiển thị với biến bên ngoài phương thức.

using System;
var john = new User{
   Name = "John",
   Salary = 50000
};
Promote(john);
Console.WriteLine(john.Salary); // prints 60000
static void Promote(User u){
   u.Salary += 10000;
   Console.WriteLine(u.Salary); // prints 60000
}

Tuy nhiên, nếu bạn thay đổi giá trị của chính biến bên trong phương thức, thì thay đổi đó không được phản ánh bên ngoài phương thức, vì chỉ một bản sao đã được thay đổi, không phải đối tượng thực tế. Ví dụ:chúng ta có thể gán đối số là null bên trong phương thức và biến thực tế sẽ không thay đổi.

using System;
var john = new User{
   Name = "John",
   Salary = 50000
};
Promote(john);
Console.WriteLine(john.Salary); // prints 50000
static void Promote(User u){
   u = null;
}

C # cho phép ba từ khóa bổ trợ khác nhau sử dụng mà bạn có thể kiểm soát các tham số của phương thức.

Công cụ sửa đổi tham chiếu

C # cho phép bạn chuyển các tham số bằng cách tham chiếu bằng cách sử dụng ref bổ nghĩa. Không quan trọng nếu biến được truyền thuộc về kiểu tham chiếu hay kiểu giá trị. Cả tham số và đối số sẽ tham chiếu đến cùng một vị trí bộ nhớ.

Trong ví dụ sau, đặt đối số u thành null cũng sẽ làm cho biến john là null, gây ra ngoại lệ tham chiếu null.

Ví dụ

using System;
var john = new User{
   Name = "John",
   Salary = 50000
};
Promote(ref john);
Console.WriteLine(john.Salary); // throws System.NullReferenceException
static void Promote(ref User u){
   u = null;
}

Đối số được truyền với một công cụ sửa đổi ref phải được khởi tạo trước khi nó được truyền.

Công cụ sửa đổi ngoài

Nó tương tự như công cụ sửa đổi tham chiếu, ngoại trừ

  • Đối số không cần phải được khởi tạo trước khi nó đi vào hàm

  • Đối số phải được khởi tạo (gán cho) trước khi nó ra khỏi hàm.

Trong ví dụ bên dưới, hàm Hire khởi tạo một đối tượng người dùng mới được chuyển cho nó thông qua công cụ sửa đổi out. Lưu ý rằng biến là biến john được khai báo nhanh khi gọi phương thức Hire.

using System;
Hire(out User john);
Console.WriteLine(john.Salary); // prints 50000
static void Hire(out User u){
   u = new User{
      Name = "John",
      Salary = 50000
   };
}

Giống như ref công cụ sửa đổi, một biến được đánh dấu bằng out sửa đổi được chuyển bằng tham chiếu.

Thường là ra biến được sử dụng để nhận nhiều giá trị trả về từ một hàm như sau -

using System;
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}"); // prints 5000
static bool Raise(int salary, out double hike){
   hike = salary * 0.1;
   return hike < 7000;
}

Công cụ sửa đổi in

Nó tương tự như ref ra tham số, ngoại trừ phương thức chấp nhận in giá trị của đối số không thể sửa đổi đối số. Nếu nó cố gắng, trình biên dịch C # sẽ tạo ra lỗi thời gian biên dịch.

trong tham số lưu trình biên dịch sao chép bộ nhớ của kiểu giá trị lớn vào biến tham số, đồng thời ngăn đối tượng không bị sửa đổi ngẫu nhiên. Điều này làm cho chúng rất hữu ích khi truyền một kiểu giá trị lớn cho phương thức.

var point = new Coord();
Verify(point);
static void Verify(in Coord c){
   // error: Cannot assign to variable 'in Coord' because it is a readonly variable
   c = new Coord();
}
struct Coord{
   public int X;
   public int Y;
}

Ví dụ

using System;
class Program{
   static void Main(){
      int number = 8;
      Increase(number);
      Console.WriteLine(number); // prints 8
      var john = new User { Name = "John", Salary = 50000 };
      Promote(john);
      Console.WriteLine(john.Salary); // prints 60000
      Leave(john);
      Console.WriteLine(john.Salary); // prints 60000

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

      User dave;
      Hire(out dave);
      Console.WriteLine(dave.Salary); // prints 50000
   }
   static void Increase(int num){
      num = num + 1;
      Console.WriteLine(num); // prints 9
   }
   static void Promote(User u){
      u.Salary += 10000;
      Console.WriteLine(u.Salary); // prints 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; }
}

Đầu ra

9
8
60000
60000
60000
50000