Biến cục bộ: var hay không var – C# best practices

0

Trong C#, biến cục bộ (local variable) là các biến được khai báo và sử dụng trong phạm vi một phương thức. Trong cách khai báo truyền thống bạn chỉ định tên kiểu, tên biến và (optional) gán/khởi tạo giá trị cho biến.

C# 3.0 đưa vào từ khóa var giúp bạn khai báo biến mà không cần chỉ định rõ tên kiểu. C# tự suy đoán ra kiểu của biến trong quá trình biên dịch dựa vào giá trị bạn gán cho biến. Cách thức khai báo biến mới này có tên gọi là implicit typing. Biến cục bộ khai báo với var được gọi là implicitly typed local variable. Việc suy đoán kiểu cụ thể từ giá trị được gọi là type inference (suy đoán kiểu).

Từ khóa var và cách khai báo biến mới này hỗ trợ làm việc với các kiểu nặc danh (anonymous type) cùng được giới thiệu ở phiên bản này của C#.

Sau khi xuất hiện, var trở nên phổ biến vượt qua khỏi mục tiêu ban đầu (hỗ trợ kiểu nặc danh) và được sử dụng thay thế cho cách khai báo biến “truyền thống”.

Trong bài viết này chúng ta sẽ cùng xem xét ưu/nhược điểm của việc sử dụng var so với cách truyền thống để giúp bạn làm việc hiệu quả hơn với C#.

Dùng var với kiểu nặc danh

Kiểu nặc danh (anonymous type) là những kiểu dữ liệu không có tên, chỉ đọc (readonly), chỉ có thể gán giá trị một lần lúc khởi tạo. Kiểu nặc danh thường dùng để lưu trữ dữ liệu tạm thời để tránh phải tạo ra các class nhỏ dùng một lần. Kiểu nặc danh không có tên kiểu, do đó bạn không thể dùng cách khai báo thông thường (chỉ định rõ tên kiểu).

Khi khai báo object kiểu nặc danh, bạn không có lựa chọn nào khác là dùng var:

var trump = new { FirstName = "Donald", LastName = "Trump", Email = "trump@gmail.com" };
var firstName = trump.FirstName;
var lastName = trump.LastName;

Trong ví dụ trên, trump là một object thuộc kiểu nặc danh. Nó được khai báo với từ khóa var và được khởi tạo với 3 property FirstName, LastName, Email.

Lưu ý rằng, kiểu nặc danh không thực sự là “nặc danh”. Chẳng qua tên gọi của nó là do C# compiler tự đặt ra và bạn không biết, và do đó không sử dụng được tên kiểu đó.

Dĩ nhiên, để tránh sử dụng kiểu nặc danh, bạn có thể tự tạo ra các class nhỏ riêng để chứa những thông tin tương ứng. Tuy nhiên, điều này dẫn đến là code của bạn sẽ tràn ngập các class nhỏ mà đôi khi nó chỉ được sử dụng một lần rồi bỏ.

Khi đó, bạn nên sử dụng var để C# compiler tự xác định kiểu giúp bạn trong quá trình biên dịch.

Dùng var trong LINQ projection

Khi sử dụng projection trong LINQ, bạn thường thu được kết quả là một danh sách object thuộc kiểu nặc danh.

Hãy xem một ví dụ nhỏ. Giả sử bạn có class Student như sau:

class Student
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
}

Bạn cũng có một danh sách object lưu trong biến students. Giờ bạn muốn lấy ra họ và tên của những sinh viên mà họ bắt đầu bằng “A” thông qua LINQ:

var studentsNameStartWithA = students.Where(s => s.FirstName.StartsWith("A")).Select(s => new { s.FirstName, s.LastName });

Phương thức Select như trên thực hiện công việc có tên gọi là projection: trích những thông tin cần thiết và đưa vào một object mới. Đáng chú ý là các object này thường là kiểu nặc danh.

Bạn không có lựa chọn nào khác là sử dụng var.

Dùng var khi cần tập trung vào ý nghĩa của biến thay vì tên kiểu

Khi khai báo một biến mà kiểu dữ liệu của nó nhìn rất “hiển nhiên”, bạn nên sử dụng var cùng với một tên gọi có ý nghĩa.

Lấy ví dụ khi bạn khai báo một biến như sau:

Dictionary<int, Queue<string>> jobsQueuedByRegion = new Dictionary<int, Queue<string>>();

Thứ nhất, cách khai báo này rất dài dòng khi bạn phải lặp lại Dictionary<int, Queue<string>>.

Thứ hai, bản thân kiểu dữ liệu của biến đã rất rõ ràng thông qua lệnh khởi tạo object, vậy cần gì phải chỉ rõ tên kiểu của biến nữa.

Thứ ba, do kiểu đã rõ ràng, cái lập trình viên (bạn và người đọc code của bạn) cần quan tâm hơn là ý nghĩa của biến qua tên gọi của nó chứ không phải là kiểu của biến.

Trong những trường hợp tương tự, bạn nên sử dụng var để code ngắn gọn, dễ đọc, dễ hiểu hơn, đồng thời hướng sự chú ý vào ý nghĩa của biến:

var jobsQueuedByRegion = new Dictionary<int, Queue<string>>();

Không lạm dụng var

Suy đoán kiểu với var rất tốt và tiện lợi nhưng bạn cũng đừng lạm dụng nó. Lấy ví dụ:

var thing = AccountFactory.CreateSavingsAccount();
var result = someObject.DoSomeWork(anotherParameter);

Đọc đoạn code trên bạn thấy:

(1) kiểu dữ liệu của kết quả không rõ ràng;

(2) tên biến không thể hiện rõ ý nghĩa của kết quả. Khi đó sử dụng var chỉ làm tăng thêm sự khó hiểu của code.

Khi này, nếu muốn sử dụng var, bạn nên đặt tên gọi của biến có ý nghĩa hơn:

var highestSellingProduct = someObject.DoSomeWork(anotherParameter);

Hoặc tốt hơn cả trong trường hợp này bạn nên chỉ định rõ kiểu của kết quả bằng cách khai báo biến truyền thống:

List<Product> highestSellingProduct = someObject.DoSomeWork(anotherParameter);

Không sử dụng var nếu bạn cần kiểm soát kiểu của giá trị

var f = GetMagicNumber();
var total = 100 * f / 6;
Console.WriteLine($"Declared Type: {total.GetType().Name}, Value: {total}");

Trong tình huống này bạn có biết kiểu của total là gì? Nó hoàn toàn phụ thuộc vào kết quả trả về của GetMagicNumber().

Nếu bạn tiếp tục sử dụng total trong các tính toán khác, bạn sẽ hoàn toàn không kiểm soát được kiểu dữ liệu của các kết quả sau đó.

Nếu làm dụng var như trên, bạn tự mình vứt đi quyền kiểm soát kiểu dữ liệu và phó mặc hết cho C# compiler. Dĩ nhiên, compiler luôn hoàn thành nhiệm vụ của nó, nhưng đó chưa chắc là những gì bạn muốn nhận được.

Trong những tình huống tương tự, để đảm bảo thu được kết quả có kiểu mình mong muốn, bạn không nên lạm dụng var. Hãy chỉ định rõ kiểu dữ liệu mình cần:

double total = 100 * GetMagicNumber() / 6;
Console.WriteLine($"Declared Type: {total.GetType().Name}, Value: {total}");

Sử dụng var không làm mất đi tính chất “static typing” của C#

Sử dụng suy đoán kiểu với từ khóa var không làm thay đổi tính chất định kiểu tĩnh (static typing) của C#.

Khi sử dụng var, bạn không tự mình chỉ định kiểu của biến đang được khai báo mà đẩy việc đó sang cho compiler.

Compiler tự suy đoán và đặt kiểu phù hợp vào đó cho bạn khi nó dịch mã nguồn sang mã IL (Intermediate Language – mã trung gian).

Suy đoán kiểu cũng không có điểm gì chung với định kiểu động (dynamic typing) thường gặp trong các ngôn ngữ script như JavaScript hay PHP.

Bạn không thể gán giá trị “lung tung” cho biến đã được khai báo với từ khóa var. Tất cả các chức năng kiểm tra kiểu của C# vẫn hoạt động bình thường.

Do đó, bạn vẫn có thể sử dụng đầy đủ những tính năng trợ giúp của Intellisense giống như khi chỉ định rõ kiểu với cách khai báo truyền thống.

Kết luận

Trong bài viết này chúng ta đã xem xét một số kinh nghiệm sử dụng cách khai báo biến cục bộ với từ khóa var.

Qua đây chúng ta đi đến mấy kết luận sau:

Bạn không nên sử dụng var nếu: (1) cần kiểm soát kiểu của kết quả; (2) kiểu của object có vai trò quan trọng để dễ đọc hiểu code.

Trong tất cả các trường hợp còn lại, bạn nên (và trong một số trường hợp phải) sử dụng var thay cho cách khai báo biến cục bộ truyền thống.

+ Nếu bạn thấy site hữu ích, trước khi rời đi hãy giúp đỡ site bằng một hành động nhỏ để site có thể phát triển và phục vụ bạn tốt hơn.
+ Nếu bạn thấy bài viết hữu ích, hãy giúp chia sẻ tới mọi người.
+ Nếu có thắc mắc hoặc cần trao đổi thêm, mời bạn viết trong phần thảo luận cuối trang.
Cảm ơn bạn!

Theo dõi
Thông báo của
guest

0 Thảo luận
Phản hồi nội tuyến
Xem tất cả bình luận