Bài tập - Khám phá các loại tham khảo
- 8 phút
Các kiểu tham chiếu bao gồm mảng, lớp và chuỗi. Các kiểu tham chiếu được xử lý khác với các loại giá trị liên quan đến cách lưu trữ giá trị khi ứng dụng đang thực thi.
Trong bài tập này, bạn sẽ tìm hiểu các loại tham chiếu khác với các loại giá trị như thế nào và new cách sử dụng toán tử để liên kết một biến với một giá trị trong bộ nhớ của máy tính.
Các kiểu tham chiếu khác với các kiểu giá trị như thế nào
Biến loại giá trị lưu trữ các giá trị của nó trực tiếp trong một khu vực lưu trữ được gọi là ngăn xếp. Ngăn xếp là bộ nhớ được phân bổ cho mã hiện đang chạy trên CPU (còn được gọi là ngăn xếp khung, hoặc kích hoạt khung). Khi khung xếp chồng đã hoàn tất thực thi, các giá trị trong ngăn xếp sẽ bị loại bỏ.
Biến loại tham chiếu lưu trữ các giá trị của nó trong một vùng bộ nhớ riêng biệt được gọi là đống. Đống là một khu vực bộ nhớ được chia sẻ trên nhiều ứng dụng chạy trên hệ điều hành cùng một lúc. .NET Runtime liên lạc với hệ điều hành để xác định những địa chỉ bộ nhớ nào khả dụng và yêu cầu địa chỉ nơi có thể lưu trữ giá trị. Thời gian chạy .NET lưu trữ giá trị, rồi trả về địa chỉ bộ nhớ cho biến số. Khi mã của bạn sử dụng biến số, .NET Runtime liền mạch tra cứu địa chỉ được lưu trữ trong biến và truy xuất giá trị được lưu trữ ở đó.
Tiếp theo, bạn sẽ viết một số mã minh họa những ý tưởng này rõ ràng hơn.
Xác định biến loại tham chiếu
Xóa hoặc sử dụng toán tử chú thích
//để nhận xét tất cả mã từ các bài tập trước đó.Cập nhật mã của bạn trong Trình soạn thảo Mã Visual Studio như sau:
int[] data;Mã trước xác định một biến có thể chứa giá trị của mảng kiểu
int.Tại thời điểm này,
datachỉ là một biến có thể giữ một tham chiếu, hoặc đúng hơn, một địa chỉ bộ nhớ của một giá trị trong đống. Vì địa chỉ này không trỏ đến địa chỉ bộ nhớ nên địa chỉ này được gọi là tham chiếu null.Tạo phiên bản mảng bằng
intcách sử dụng từnewkhóaCập nhật mã của bạn trong Trình soạn thảo Mã Visual Studio để tạo và gán phiên bản mảng
intmới, bằng cách sử dụng mã sau:int[] data; data = new int[3];Từ
newkhóa thông báo cho .NET Runtimeintbiết cách tạo phiên bản mảng, rồi phối hợp với hệ điều hành để lưu trữ mảng có kích thước cho ba giá trị int trong bộ nhớ. .NET Runtime tuân thủ và trả về địa chỉ bộ nhớ của mảngintmới. Cuối cùng, địa chỉ bộ nhớ được lưu trữ trong dữ liệu biến. Cácintthành phần của mảng mặc định là giá trị0, vì đó là giá trị mặc định củaintmột .Sửa đổi ví dụ về mã để thực hiện cả hai thao tác trong một dòng mã
Hai dòng mã trong bước trước đó thường được rút ngắn thành một dòng mã để cả hai tuyên bố các biến, và tạo ra một thể hiện mới của mảng
int. Sửa đổi mã từ bước 3 sang bước sau đây.int[] data = new int[3];Trong khi không có đầu ra để quan sát, hy vọng bài tập này đã làm rõ hơn mối quan hệ của cú pháp C# với các bước của quy trình để làm việc với các loại tham chiếu.
Kiểu dữ liệu chuỗi C# có gì khác biệt?
Kiểu string dữ liệu cũng là một kiểu tham chiếu. Bạn có thể thắc mắc tại sao toán new tử không được sử dụng khi khai báo chuỗi. Đây hoàn toàn là một sự tiện lợi được cung cấp bởi các nhà thiết kế của C#. Vì kiểu dữ string liệu được sử dụng thường xuyên nên bạn có thể sử dụng định dạng này:
string shortenedString = "Hello World!";
Console.WriteLine(shortenedString);
Tuy nhiên, ở hậu trường, một phiên bản mới của được System.String tạo và khởi tạo thành "Hello World!".
Các vấn đề thực tiễn khi sử dụng các loại giá trị và tham chiếu
-
Loại Giá trị (số nguyên): Trong ví dụ này,
val_Avàval_Blà các kiểu giá trị số nguyên.
int val_A = 2;
int val_B = val_A;
val_B = 5;
Console.WriteLine("--Value Types--");
Console.WriteLine($"val_A: {val_A}");
Console.WriteLine($"val_B: {val_B}");
Bạn sẽ thấy đầu ra sau đây:
--Value Types--
val_A: 2
val_B: 5
Khi val_B = val_A được thực thi, giá trị của sẽ val_A được sao chép và lưu trữ trong val_B. Vì vậy, khi val_B được thay đổi, val_A vẫn không bị ảnh hưởng.
-
Loại Tham chiếu (mảng): Trong ví dụ này,
ref_Avà làref_Bcác kiểu tham chiếu mảng.
int[] ref_A= new int[1];
ref_A[0] = 2;
int[] ref_B = ref_A;
ref_B[0] = 5;
Console.WriteLine("--Reference Types--");
Console.WriteLine($"ref_A[0]: {ref_A[0]}");
Console.WriteLine($"ref_B[0]: {ref_B[0]}");
Bạn sẽ thấy đầu ra sau đây:
--Reference Types--
ref_A[0]: 5
ref_B[0]: 5
Khi ref_B = ref_A được thực hiện, trỏ ref_B tới cùng một vị trí bộ nhớ như ref_A. Vì vậy, khi ref_B[0] được thay đổi, cũng ref_A[0] thay đổi vì cả hai đều trỏ đến cùng một vị trí bộ nhớ. Đây là sự khác biệt chính giữa các kiểu giá trị và kiểu tham chiếu.
Recap
- Các loại giá trị có thể chứa các giá trị nhỏ hơn và được lưu trữ trong ngăn xếp. Các kiểu tham chiếu có thể chứa các giá trị lớn và một phiên bản mới của kiểu tham chiếu được tạo bằng cách dùng toán
newtử. Loại tham chiếu biến giữ một tham chiếu (địa chỉ bộ nhớ) giá trị thực tế được lưu trữ trong đống. - Các kiểu tham chiếu bao gồm mảng, chuỗi và lớp.