Chuyển đến nội dung chính

Giới thiệu về kiểu Generic trong C#

Bài viết này nhằm giới thiệu về cách lập trình Generic trong C#. Bài viết được đăng trên trang lập trình Jou.vn

Giới thiệu về Generic Type

Generic là 1 tính năng mới trong .NET Framework 2.0 và và được tích hợp sâu trong Common Language Runtime (CLR).  Trong .NET Framework, Generic được giới thiệu là khái niệm về các kiểu tham số và được dùng để thiết kế class và phương thức nhằm để trì hoãn chỉ ra kiểu dữ liệu cho đến khi lớp hoặc phương thức được khai báo hoặc khởi tạo.
Ví dụ, bằng cách sử dụng tham số T là tham số chung, bạn có thể tạo 1 class duy nhất mà khi tham chiếu tới, bạn sẽ không gặp bất kỳ lỗi nào xảy ra trong lúc runtime khi ép kiểu hoặc boxing (chuyển giá trị từ value type sang reference type)

Tại sao phải sử dụng kiểu Generic

Một trong những điểm nổi bật của kiểu Generic là cho phép bạn kiểm tra cú pháp trong lúc biên dịch. Bạn có thể sử dụng nhiều kiểu dữ liệu khác nhau với cùng 1 đoạn code (tương tự như khái niệm Template trong C++)
Giả sử đầu tiên bạn thiết kế stack để chứa dữ liệu kiểu int:

    public class IntStack
    {
        readonly int[] _dataArray = new int[100];
        int _currentPos;
        public void Push(int value)
        {
            _dataArray[_currentPos++] = value;
        }
        public int Pop()
        {
            return _dataArray[--_currentPos];
        }
    } 
 

Stack cho phép bạn lưu trữ và nhận dữ liệu theo kiểu LIFO (Last In First Out). Phương thức Push() dùng để đưa dữ liệu vào stack. Phương thức Pop() dùng để nhận dữ liệu từ Stack. Bạn có thể tham khảo thêm ở wikipedia

        /// <summary>
        /// Example Int Stack
        /// </summary>
        static void Example1()
        {
            // create a new IntStack 
            var stack = new IntStack();
            // push some values into the stack 
            stack.Push(2);
            stack.Push(4);
            stack.Push(8);
            // pop values from the stack 
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine("Pop value: {0}", stack.Pop());
            } 
        }
 
Và nếu vào một ngày đẹp trời nào đó, bạn muốn stack lưu trữ kiểu string (stack kiểu int vẫn sử dụng). Thay vì copy và sửa lại, bạn nhận thấy rằng, mọi kiểu dữ liệu được dẫn xuất từ System.Object. Bạn vui mừng và sửa lại:

    public class ObjectStack
    {
        readonly object[] _dataArray = new object[10];
        int _currentPos;
        public void Push(object value)
        {
            _dataArray[_currentPos++] = value;
        }
        public object Pop()
        {
            return _dataArray[--_currentPos];
        }
    }
 
Vấn đề đã được giải quyết, nhưng lại nảy sinh 1 vấn đề khác. Chúng ta muốn stack lưu trữ dữ liệu với kiểu dữ liệu được chỉ ra, nhưng với kiểu object, stack nhận bất kỳ kiểu dữ liệu.

        /// <summary>
        /// Object Stack
        /// </summary>
        static void Example2()
        {
            var stack = new ObjectStack();
            stack.Push("2");
            stack.Push(4);
            stack.Push(8);
            // pop values from the stack 
            for (int i = 0; i < 3; i++)
            {
                var a = (int)stack.Pop();
                Console.WriteLine("Pop value: {0}", a);
            } 
        }
 

Vấn đề là nếu ai đó muốn xài stack kiểu int nhưng lại nhập vào chữ “2”, trình biên dịch sẽ không báo lỗi cho đến lúc runtime


Để khắc phục được điều này, chúng ta sử dụng kiểu Generic.

Sử dụng Generic Type

Đối với 1 class, bạn khai báo như sau:
 Với T là kiểu bạn truyền vào cho class.
Tương tự với methods, interface, chúng ta khai báo như sau:

    public class GenericMethods
    {
        public void DoSomething<T, TV>(T a, TV b)
        {
            //Do something
        }
    }

    public interface ISessionChannel<TSession> { /*...*/ }
 

Bạn có thể tham khảo chi tiết tại trang MSDN

Ví dụ tạo 1 Generic Stack

Cách dễ nhất để tạo 1 generic class là bạn hãy tạo 1 class non-generic trước, và sau đó hãy chuyển sang generic class sau.
Sau đây tôi sẽ ví dụ chuyển bài Stack từ kiểu int sang kiểu T:
Chuyển public class GenericStack{} sang public class GenericStack<T>{}
Và bạn thay chỗ nào là kiểu “int” thành kiểu “T”

    class GenericStack<T> 
    {
        readonly T[] _dataArray = new T[10]; 
        int _currentPos; 
        public void Push(T value) {
            _dataArray[_currentPos++] = value;
        }
        public T Pop()
        {
            return _dataArray[--_currentPos];
        }
        public T this[int index]
        {
            get
            {
                return _dataArray[index];
            }
        }
    }
 

Sử dụng GenericStack:

        /// <summary>
        /// Generic Stack
        /// </summary>
        static void Example3()
        {
            var stack = new GenericStack<int>();
            stack.Push(2);
            stack.Push(4);
            stack.Push(8);
            // pop values from the stack 
            for (int i = 0; i < 3; i++)
            {
                var a = stack.Pop();
                Console.WriteLine("Pop value: {0}", a);
            }
        }
 

Lưu ý: Có một số trường hợp khi thay từ kiểu cụ thể sang kiểu T sẽ bị lỗi. (Kiểu T không hỗ trợ phép toán +, -, *, /…; hoặc 1 số hàm trên kiểu dữ liệu cụ thể).
Các bạn có thể tải ví dụ tại: Mediafire

Kết luận

Trong bài viết này, tôi đã giới thiệu cho bạn cách dùng kiểu Generic và xây dựng 1 class GenericStack đơn giản. Hi vọng qua ví dụ đó, giúp bạn phần nào nắm được ý nghĩa và tầm quan trọng của kiểu Generic trong lập trình. Chúc các bạn thành công.
Án Bình Trọng 's Blog

Nhận xét

Bài đăng phổ biến từ blog này

[ASP.NET MVC] Authentication và Authorize

Một trong những vấn đề bảo mật cơ bản nhất là đảm bảo những người dùng hợp lệ truy cập vào hệ thống. ASP.NET đưa ra 2 khái niệm: Authentication và Authorize Authentication xác nhận bạn là ai. Ví dụ: Bạn có thể đăng nhập vào hệ thống bằng username và password hoặc bằng ssh. Authorization xác nhận những gì bạn có thể làm. Ví dụ: Bạn được phép truy cập vào website, đăng thông tin lên diễn đàn nhưng bạn không được phép truy cập vào trang mod và admin.

ASP.NET MVC: Cơ bản về Validation

Validation (chứng thực) là một tính năng quan trọng trong ASP.NET MVC và được phát triển trong một thời gian dài. Validation vắng mặt trong phiên bản đầu tiên của asp.net mvc và thật khó để tích hợp 1 framework validation của một bên thứ 3 vì không có khả năng mở rộng. ASP.NET MVC2 đã hỗ trợ framework validation do Microsoft phát triển, tên là Data Annotations. Và trong phiên bản 3, framework validation đã hỗ trợ tốt hơn việc xác thực phía máy khách, và đây là một xu hướng của việc phát triển ứng dụng web ngày nay.

Tổng hợp một số kiến thức lập trình về Amibroker

Giới thiệu về Amibroker Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”. AFL trong Amibroker là ngôn ngữ xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng (các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên excel.