Hiểu rõ về nullable trong C#

1
2742
nullable trong c#

Mở đầu

Từ C# 2.0, Microsoft đã giới thiệu với chúng ta về một kiểu dữ liệu mới rất đặc biệt có tên là nullable. Vậy thực chất, nullable là gì và tại sao nó cần được sử dụng, hãy cùng đi tìm hiểu ở các phần ngày sau đây.

ảnh minh họa: pvs-studio

Tại sao phải sử dụng nullable ?

nullable cực kì hữu ích khi xử lý các giá trị trên cơ sử dữ liệu, khi các giá trị được trả về trog table là NULL. Hãy thử tưởng tượng một giá trị số nguyên trong table là NULL, chỉ có thể được biểu diễn bằng 0 nếu biến C# không thể có giá trị rỗng tức số nguyên thông thường.

Ví dụ: bạn yêu cầu khách hàng của mình đăng kí tài khoản, và trong đó có yêu cầu khách hàng nhập ngày sinh của mình vào, điều này là không bắt buộc và người khách đó có thể bỏ qua vấn đề này. Nhưng lúc này, vấn đề nảy sinh với bạn. Giá trị ngày tháng trong C# là một kiểu giá trị System.DateTime, và đây là một kiểu giá trị nó sẽ không chấp nhận một giá trị là null, do đó nó sẽ có một giá trị mặc định.

Cho nên, khi khách hàng chưa điền một giá trị rõ ràng hoặc bỏ qua giá trị đó, bạn sẽ cần một vài câu lệnh logic trước khi lưu nó trong cơ sở dữ liệu là NULL, trong cơ sở dữ liệu các giá trị DateTime có thể được gán là NULL. Để tránh các bước kể trên và làm cho code dễ đọc hơn chúng ta sẽ sử dụng nullable.

Ngoài ra, các biên nullable có giá trị là null thường được gọi là không có gì, trống rỗng.

Khai báo nullable trong C#

Cú pháp để khai báo một kiểu nullable như sau:

hoặc

Bạn lưu ý khai báo thêm là dấu ? và ở cách 2 thì hai vị trí kiểu dữ liệu là giống nhau. Cả hai cách khai báo này sẽ gán cho biến có giá trị mặc định là null. Sau đây là đoạn code ví dụ:

Sau đây là output của chương trình:

Ở chương trình trên, mình đã sử dụng 3 cách khai báo nullable ở trên. Trong đó, có 2 cách đã được mình trình bay khi khai báo sẽ có giá trị là null. Và ta nhận thấy rằng một biến nullable khi được gán giá trị thì nó không khác gì một kiểu dữ liệu bình thường. Còn khi biến nullable đó có giá trị là null khi xuất ra màn hình console, chúng ta sẽ không thấy gì cả.

Phép toán null-coalescing ??

Toán tử ?? là một toán tử hai ngôi cũng được giới thiệu từ C# 2.0. Với toán tử này sẽ làm cho code bạn sạch, gọn và trông sáng hơn rất nhiều vì nó rút gọn được các cấu trúc logic mà bạn thường sử dụng trước khi nó xuất hiện.

Chức năng của toán tử ??

Đầu tiên, chúng ta có cách sử dụng của toán tử ?? như sau:

Tiếp theo đó, chúng ta sẽ có các ví dụ rồi từ đó rút ra kết luận thực sự toán tử dùng ?? để làm gì ?

Chương trình trên cho ra kết quả:

Bằng một cách thần kỳ nào đó, chương trình cho ra kết quả là 15000, giờ chúng ta thử thay đổi đi một chút xem có gì khác biệt không nhé.

Ở chương trình sau khi thay đổi, output của chương trình như sau:

Ta có thể thấy chương trình trước và sau khi thay đổi có sự khác biệt. Khi biến a có giá trị là null thì b nhận giá trị là 15000, còn khi biến a có giá trị khác với null thì biến b lại mang giá trị của a.

Từ đó, chúng ta có thể kết luận được cách hoạt động của toán tử ?? là khi giá trị của toán hạng đầu tiên là null, thì toán tử sẽ trả về giá trị của toán hạng thứ 2 giống như là ở ví dụ trên mà a có giá trị là null. Còn ngược lại, tức giá trị của toán hạng đầu tiên khác null thì toán tử sẽ trả về giá trị của toán hạng đầu tiên.

Lỗi NullReferenceException khi sử dụng nullable

Lỗi NullReferenceException là loại lỗi xuất hiện khi bạn sử dụng một biến mà biến đó không trỏ tới bất kỳ một object cụ thể nào.

Trong C# .NET, khi sử dụng một biến dạng nullable và chứa giá trị null khi thao tác trên nó (ngoại trừ việc xuất ra màn hình console) đều dẫn tới lỗi NullReferenceException. Nhưng lỗi này khi thực hiện viết code thì chúng ta thường k lường hết được chúng trong khi code của bạn vẫn có thể compile (biên dịch) bình thường, chỉ có khi chạy hoặc test chương trình mới có thể phát hiện ra.
Để đảm bảo không phát sinh lỗi trên các lập trình viên thường sử dụng một vài đoạn code logic để có thể kiểm tra giá trị của biến trước khi thực hiện bất kỳ thao tác nào trên nó, nên code thường dài và gây rối khi kiểm tra lại code.

Nhận thấy điều này C# quyết định đưa ra thêm 2 phép toán mới là ?. và ?[] bắt đầu từ phiên bản C# 6.

Phép toán null-conditional ?. và ?[]

Như đã được trình bày ở trên 2 phép toán này được thêm vào từ phiên bản C# 6, đối với phép toán ?. thì được dùng cho các class member còn phép toán ?[] được dùng cho phần tử của mảng, danh sách.

Chúng ta cùng xét một đoạn code nhỏ để ví dụ cho phép toán ?.:

Khi chạy chương trình này dòng code thứ sẽ báo lỗi NullReferenceException vì giá trị của s là null. Nhưng nếu bạn sửa code thành như sau:

Khi này ví giá trị của s là null nên chương trình sẽ không gọi tiếp property Length để lấy độ dài của chuỗi nữa. Vậy nên chương trình hoạt động bình thường.

Phép toán ?. hoặc động bằng cách nếu object đó có giá trị là null thì chương trình sẽ ngừng gọi đến member cần gọi của object đó và trả về giá trị là null, còn ngược lại thì phép toán này sẽ tương tự như phép toán . (phép toán truy xuất member).

Tương tự như vậy, phép toán ?[] hoạt động bằng cách nếu mảng / danh sách đó khác null thì chương trình sẽ ngừng gọi đến phần tử cần truy xuất và giá trị trả về là null, còn ngược lại thì phép toán này sẽ tương tự như phép toán [] (phép toán truy xuất phần tử).

Nhờ có 2 phép toán này mà lập trình viên có thể hạn chế khả năng xảy ra NullReferenceException.

Lưu ý: giá trị trả về của cả 2 phép toán trên đều là giá trị kiểu nullable, tức là giá trị trả về có thể là null vậy nên chúng ta phải dùng một biến có kiểu nullable để lưu trữ giá trị trả về của phép toán.

Tổng kết

Như vậy, thông qua bài viết ngày hôm nay chúng ta có thể hiểu được khái niệm về nullable trong ngôn ngữ lập trình C#, toán tử ???. và ?[], cách phát hiện và xử lý lỗi NullReferenceException trong C#. Mình nghĩ bài viết này tới đây cũng là khá dài rồi. Cảm ơn bạn đã đọc bài viết và đừng quên ủng hộ Lập trình không khó trong các bài viết tiếp theo nhé !

Subscribe
Notify of
guest
1 Bình luận
Inline Feedbacks
View all comments