C#. keep it short, get it done

Bài Viết này được trích bài viết cùng tên của David Fells.

Nếu mục tiêu của bạn đặt ra là viết code hiệu quả nhất có thể bạn sẽ muốn đọc bài viết này. Bài viết này sẽ bàn đến 3 vấn đề thường được bỏ qua trong cấu trúc ngôn ngữ C#, giúp chỉ trong vài dòng code có thể hoàn thành nhiệm vụ của mình.

Các nhà phát triển ngày nay có rất nhiều ngôn ngữ hướng đối tượng để lựa chọn, hầu hết các nhà phát triển kết thúc việc tìm hiểu sâu về ngôn ngữ lập trình sớm hơn. Kết quả là, rất nhiều lập trình viên không bao giờ tìm hiểu việc hoạt động ở các cấp thấp hơn của các ngôn ngữ .Net runtime, và nội dung bên của nó vượt ra ngoài phạm vi của bài viết này. Trong thực tế, bài viết này giả định rằng người đọc đã có kiến thức căn bản về cách khởi tạo và chạy IL.

Một trong những tính năng vượt trội của ngôn ngữ hiện đại như C# là các nhà phát triển không cần phải lo lắng về việc quản lý bộ nhớ và thu gom rác (memory management and garbage collection). Các nhà phát triển thường bỏ qua chúng và trở nên tự mãn về vấn đề này – tuy nhiên chúng ta phải phấn đấu để viết code hiệu quả nhất có thể. Tính hiệu quả tôi đề cập đến ở đây là: viết những dòng code ít nhất có thể trong việc xây dựng các tính năng của ngôn ngữ để hoàn thành nhiệm vụ lập trình.

Trong bài này, chúng ta sẽ xem xét 3 bấn đề trong cấu trúc ngôn ngữ C#, trong quan sát của tác giả, bị bỏ hầu hết bởi các nhà phát triển (developers). Đầu tiên, chúng ta sẽ xem xét các khai báo “using”, việc cung cấp một cấu trúc “try/ catch” và việc cải thiện vấn đề sử lý rác thải (improved garbage disposal). Cùng với khai báo “using” chúng ta sẽ xem xét lại mô hình chuẩn “Dispose” (thực hiện “IDisposable” giao diện) Chúng ta cũng sẽ kiểm tra lại việc khai thác cấu trúc “is” và “as” cùng nhau. Từ khóa “is” cung cấp một cơ chế tự động cho việc đối chiếu của một loại đối tượng, và “as” cung cấp một cơ chế an toàn, loại bỏ chính xác.

Nói chung, bạn không cần phải lo lắng về xử lý (disposal). Ngoại lệ (exception) chính, tuy nhiên, là khi bạn đang sử dụng một nguồn không được quản lý – như một kết nối cơ sở dữ liệu hay tập tin cố định – hoặc một một nguồn nào khác ngoại trừ bộ nhớ. .NET framework cung cấp giao diện “IDisposable” cho mục đích này. Vì không có cách nào để đảm bảo rằng phương thức “Dispose()” nhận được lời gọi, nó được coi là một kỹ thuật đóng gọi tốt nhất cho một lời gọi  đến phương thức “Dispose()” trong một đối đối tượng finalizer (destructor). (Finalizer là một phương thức đặc biệt, nó được thực thi khi một đối tượng là rác được thu thập, nó tương đối giống như hàm hủy(destructor)).

Khi bộ gom rác (garbage collection) thực thi, tất cả các đối tượng với finalizer ở lại trong bộ nhớ và các finalizer của chúng thực thi. Đối tượng mà không phải là các finalizer chỉ đơn giản là xóa khỏi bộ nhớ – đó là nơi mà các nguồn tài nguyên không được quản lý có khả năng xảy ra rò rĩ bộ nhớ.

Dưới đây là giao diện “IDisposable”:

public interface IDisposable
{
void Dispose();
}

Các mã sau minh họa việc sử dụng cơ bản của giao diện “IDisposable”.

public class MyClass : IDisposable
{
private bool _isDisposed = false;
~MyClass()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(true);
}
protected virtual void Dispose(bool isDisposing)
{
if (_isDisposed)
return;
if (isDisposing)
{
// Free managed resources
}
// Free unmanaged resources here
_isDisposed = true;
}
}

Bạn có thể hỏi tại sao có một phiên bản ảo quá tải của các phương thức “Dispose()” ở mã lệnh trên. Chúng ta tạo ra phương thức ảo để sử dụng như một móc nối cho các lớp dẫn xuất để gọi phương thức xử lý các lớp cơ sở, do đó đảm bảo rằng các tài nguyên được cấp phát đúng cách.

Điều quan trọng nhất cần nhớ khi thực hiện xử lý là bạn nên giải phóng tài nguyên trong phương thức “Dispose()”, mà không phải trong cách khác. Không gọi bất kỳ đối tượng phương thức hoặc tạo ra các tham chiếu đến các đối tượng hiện tại hoặc làm bất cứ điều gì khá mà hiệu quả có thể phục hồi lại các đối tượng. Hãy nhớ rằng, bạn không bao giờ biết những gì mà các đối tượng sẽ sử lý, do đó, bạn có thể đang làm việc trên một đối tượng đã được xử lý hay hoàn tất. Như vậy, đối với danh sách các đối tượng được khai báo tòa cục thì bộ gom rác sẽ không biết và xử lý nó lại lần nữa, bởi vì nó đã được thực hiện.

Khai báo “using” là một trong những cách tốt nhất để xem nó là tài nguyên thực sự được xử lý đúng cách. Cấu trúc này cung cấp một khai báo hiệu quả “try/ catch”, trong đó các đối tượng tham chiếu trực tiếp bởi mệnh đề “using()” được xử lý một cách rõ ràng trong khối cuối cùng. Hai ví dụ sau đây sẽ đề xuất cơ bản về sự giống nhau giữ IL và các tác dụng tương tự.

MyClass obj = null;
try
{
obj = new MyClass();
obj.DoSomething();
}
finally {
if (null != obj)
obj.Dispose();
}

using (MyClass obj = new MyClass())
{
obj.DoSomething();
}

And

protected DataGrid MyGrid;

private void Page_Load(object sender, System.EventArgs e)
{
using (SqlConnection dbCxn = new SqlConnection(“connection
string”))
{

dbCxn.Open();
string sql = “SELECT * FROM MyTable”;
using (SqlCommand dbCmd = new SqlCommand(dbCxn, sql))
{

using (DataReader reader =                                                       dbCmd.ExecuteReader(CommandBehavior.CloseConnection))
{
MyGrid.DataSource = reader;
MyGrid.DataBind();
}
}
}
}

Các bạn có thể tham khảo thêm tại trang gốc của bài viết

Advertisements

About thanhcuong1990

Handsome and talent!! ^^
This entry was posted in C# and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s