C# Cơ bản .NET Core §1 Cài đặt, chương trình C# đầu tiên §2 Biến, kiểu dữ liệu và nhập/xuất §3 Toán tử số học và gán §4 So sánh, logic và lệnh if, switch §5 Vòng lặp for, while §6 Phương thức - Method §7 Chuyển số thành chữ §8 Phương thức - Delegate §9 Lớp - Class §10 Namespace §11 Partial, Nested §12 Kiểu giá trị, tham chiếu §13 Kiểu vô danh và dynamic §14 Biểu thức lambda §15 Event §16 Hàm hủy - Quá tải toán tử - thành viên tĩnh - indexer §17 null và nullable §18 Mảng §19 Chuỗi ký tự §20 Tính kế thừa §21 Phương thức khởi tạo §22 Tính đa hình - abstract - interface §23 Struct và Enum §24 Ngoại lệ Exeption §25 IDisposable - using §26 File cơ bản §27 FileStream §28 Generic §29 Collection - List §30 SortedList §31 Queue / Stack §32 Linkedlist §33 Dictionary - HashSet §34 Phương thức mở rộng §35 ObservableCollection §36 LINQ §37 (Multithreading) async - bất đồng bộ §38 Type §39 Attribute Annotation §40 DI Dependency Injection §41 (Multithreading) Parallel §42 Thư viện lớp §43 (Networking) Uri, Dns, Ping §44 (Networking) HttpClient §45 (Networking) HttpMessageHandler §46 (Networking) HttpListener §47 (Networking) Tcp TcpListenerr/TcpClient §48 (ADO.NET) SqlConnection §49 (ADO.NET) SqlCommand §50 (ADO.NET) DataAdapter §51 (EF Core) Tổng quan §52 (EF Core) Tạo Model §53 (EF Core) Fluent API §54 (EF Core) Query §55 (EF Core) Scaffold §56 (EF Core) Migration §57 (ASP.NET CORE) Hello World! §58 (ASP.NET CORE) Middleware §59 (ASP.NET CORE) Map - Request - Response §60 (ASP.NET CORE) IServiceCollection - MapWhen §61 (ASP.NET CORE) Session - ISession §62 (ASP.NET CORE) Configuration §63 (ASP.NET CORE) Gửi Mail §64 (ASP.NET CORE) SASS/SCSS §65 (ASP.NET CORE) LibMan §66 (ASP.NET RAZOR) Khởi tạo và Route §67 (ASP.NET RAZOR) Cú pháp Razor §68 (ASP.NET RAZOR) Layout trong ASP.NET Core §69 (ASP.NET RAZOR) Partial §70 (ASP.NET RAZOR) ViewComponent §71 (ASP.NET RAZOR) TagHelper §72 (ASP.NET RAZOR) HtmlHelper §73 (ASP.NET RAZOR) PageModel §74 (ASP.NET RAZOR) Model Binding §75 (ASP.NET RAZOR) HTML Form, Validation §76 (ASP.NET RAZOR) Upload File §77 (ASP.NET RAZOR) Entity Framework §78 (ASP.NET RAZOR) Paging §79 (ASP.NET RAZOR) Identity (1) - Register, Login, Logout §80 (ASP.NET RAZOR) Identity (2) Lockout, Reset Password §81 (ASP.NET RAZOR) Identity (3) Google Login §82 (ASP.NET RAZOR) Identity (4) Facebook Login §83 (ASP.NET RAZOR) Identity (5) profile, password, email ... §84 (ASP.NET RAZOR) Identity (6) Role §85 (ASP.NET RAZOR) Identity (7) Role-based Authorization §86 (ASP.NET RAZOR) Identity (8) RoleClaim §87 (ASP.NET RAZOR) Identity (9) Authorization Handler §88 (ASP.NET RAZOR) IAuthorizationService §89 (ASP.NET MVC) Controller - View §90 (ASP.NET MVC) Route §91 (ASP.NET MVC) EF, Identity §92 (ASP.NET MVC) Binding, Validation §93 (ASP.NET MVC) Xây dựng Website(1) §94 (ASP.NET MVC) Xây dựng Website(2) §95 (ASP.NET MVC) Xây dựng Website(3) §96 (ASP.NET MVC) Xây dựng Website(4) §97 (ASP.NET MVC) Giỏ hàng - Cart (5) §98 (ASP.NET MVC) elFinder (5) §99 (ASP.NET MVC) SB Admin (6) §100 (ASP.NET MVC) Kestrel, publish
Dictionary - HashSet (Bài trước)

Các phương thức mở rộng trong C#

Các phương thức mở rộng là các phương thức thêm vào lớp, cấu trúc, giao diện có sẵn mà không cần thiết phải kế thừa lớp để tạo ra các lớp mới, không cần biên dịch lại thư viện. Các phương thức mở rộng khai báo là những phương thức tĩnh, nhưng lại được gọi thông qua đối tượng lớp mà phương thức mở rộng đó khai báo.

Kỹ thuật dùng hàm mở rộng để bổ sung các tính năng cho thư viện sẵn có được dùng rất nhiều trong thư viện LINQ - để mở rộng chức năng cho các IEnumerable

Xem ví dụ sau:

using System.Collections.Generic;

namespace CS020_ExtensionMethod
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> ls = new List<int>() {1,2,3,4};
            var ps = ls.Where(i => i >= 3);             // Lỗi vì List không có phương thức Where
        }
    }
}

Giờ sửa lại code như sau:

using System.Collections.Generic;
using System.Linq;                                      // Nạp thư viện LINQ

namespace CS020_ExtensionMethod
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> ls = new List<int>() {1,2,3,4};
            var ps = ls.Where(i => i >= 3);             // Linq đã mở rộng thêm vào List phương thức Where
        }
    }
}

Khai báo phương thức mở rộng

Hãy tạo một phương thức tĩnh sau, phương thức này in chuỗi ra màn hình với màu Console nhập vào.

public static void Print(string s, ConsoleColor color = ConsoleColor.Yellow)
{
     ConsoleColor lastColor = Console.ForegroundColor;
     Console.ForegroundColor = color;
     Console.WriteLine(s);
     Console.ForegroundColor = lastColor;
}

Đây là một phương thức tĩnh bình thường, sử dụng nó để in một chuỗi ra màn hình, chuỗi nhập ở tham số thứ nhất

Print("Test string ...");

Giờ nếu muốn hàm Print như một hàm mở rộng của đối tượng kiểu string, ta sẽ thực hiện như sau:

  • Chuyển khai báo Print trong một lớp tĩnh
  • Đảm bảo Print là phương thức tĩnh
  • Tham số đầu tiên của hàm là kiểu string (lớp mà phương thức mở rộng sẽ thêm vào) cho thêm từ khóa this vào phía trước kiểu này - để cho biết sẽ mở rộng lớp string với phương thức này.
public static class MyExtensionMethods {
     public static void Print(this string s, ConsoleColor color = ConsoleColor.Yellow)
     {
         ConsoleColor lastColor = Console.ForegroundColor;
         Console.ForegroundColor = color;
         Console.WriteLine(s);
         Console.ForegroundColor = lastColor;
     }
}

Bằng cách khai báo như trên, đã mở rộng string, thêm vào nó phương thức Print, hàm này sẽ được gọi trên đối tượng lớp string.

string s = "Chuỗi kiểm tra";
s.Print();                                   // Chuỗi kiểm tra  (có màu vàng)
"Xin chào các bạn!".Print(ConsoleColor.Red); // in ra "Xin chào các bạn!" có màu đỏ

Bằng cách như vậy bạn có thể mở rộng các lớp có sẵn.

Tham khảo mã nguồn CS020_ExtensionMethod, hoặc tải về tại ex020

Dictionary - HashSet (Bài trước)