Các phương pháp mở rộng không cung cấp một cái gì đó không thể được thực hiện theo những cách khác. Chúng là đường cú pháp để làm cho sự phát triển đẹp hơn, mà không mang lại lợi ích kỹ thuật thực sự.
Phương pháp mở rộng tương đối mới. Các tiêu chuẩn và quy ước thường được quyết định bởi ý kiến phổ biến (cộng với một số kinh nghiệm lâu dài về những gì kết thúc là một ý tưởng tồi), và tôi không nghĩ rằng chúng ta có thể vẽ một đường thẳng dứt khoát mà mọi người đều đồng ý.
Tuy nhiên, tôi có thể thấy một số lập luận, dựa trên những điều tôi đã nghe từ đồng nghiệp.
1. Chúng thường thay thế các phương thức tĩnh.
Các phương thức mở rộng phổ biến nhất dựa trên những thứ mà nếu không phải là phương thức tĩnh, không phải là phương thức lớp. Chúng trông giống như các phương thức lớp, nhưng chúng không thực sự.
Các phương thức mở rộng đơn giản không nên được coi là một phương án thay thế cho các phương thức lớp; nhưng đúng hơn là một cách để cung cấp cho các phương thức tĩnh một cách tổng hợp khác một giao diện "phương pháp đo lường lớp".
2. Khi phương thức dự định của bạn là dành riêng cho một dự án tiêu thụ nhưng không phải là thư viện nguồn.
Chỉ vì bạn phát triển cả thư viện và người tiêu dùng không có nghĩa là bạn sẵn sàng đưa logic vào bất cứ nơi nào phù hợp.
Ví dụ:
- Bạn có một
PersonDto
lớp học đến từ DataLayer
dự án của bạn .
WebUI
Dự án của bạn muốn có thể chuyển đổi PersonDto
thành a PersonViewModel
.
Bạn không thể (và sẽ không muốn) thêm phương thức chuyển đổi này vào DataLayer
dự án của mình . Vì phương thức này nằm trong phạm vi của WebUI
dự án, nên nó nằm trong dự án đó.
Phương thức mở rộng cho phép bạn có phương thức này có thể truy cập toàn cầu trong dự án của bạn (và người tiêu dùng có thể có của dự án của bạn) mà không yêu cầu DataLayer
thư viện triển khai.
3. Nếu bạn nghĩ rằng các lớp dữ liệu chỉ nên chứa dữ liệu.
Ví dụ, Person
lớp của bạn chứa các thuộc tính cho một người. Nhưng bạn muốn có một vài phương thức định dạng một số dữ liệu:
public class Person
{
//The properties...
public SecurityQuestionAnswers GetSecurityAnswers()
{
return new SecurityQuestionAnswers()
{
MothersMaidenName = this.Mother.MaidenName,
FirstPetsName = this.Pets.OrderbyDescending(x => x.Date).FirstOrDefault()?.Name
};
}
}
Tôi đã thấy nhiều đồng nghiệp ghét ý tưởng trộn dữ liệu và logic trong một lớp. Tôi không hoàn toàn đồng ý với những điều đơn giản như định dạng dữ liệu, nhưng tôi thừa nhận rằng trong ví dụ trên, cảm thấy bẩn Person
khi phải phụ thuộc vào SecurityQuestionAnswers
.
Đặt phương thức này trong một phương thức mở rộng sẽ ngăn chặn lớp dữ liệu thuần túy khác.
Lưu ý rằng đối số này là một trong những phong cách. Điều này tương tự như các lớp một phần. Có rất ít hoặc không có lợi ích kỹ thuật để làm như vậy, nhưng nó cho phép bạn tách mã thành nhiều tệp nếu bạn thấy nó sạch hơn (ví dụ: nếu nhiều người sử dụng lớp nhưng không quan tâm đến các phương thức tùy chỉnh bổ sung của bạn).
4. Phương pháp trợ giúp
Trong hầu hết các dự án, tôi có xu hướng kết thúc với các lớp trợ giúp. Đây là các lớp tĩnh thường cung cấp một số tập hợp các phương thức để định dạng dễ dàng.
Ví dụ: một công ty tôi làm việc có định dạng datetime cụ thể mà họ muốn sử dụng. Thay vì phải dán chuỗi định dạng khắp nơi hoặc biến chuỗi định dạng thành biến toàn cục, tôi đã chọn phương thức mở rộng DateTime:
public static string ToCompanyFormat(this DateTime dt)
{
return dt.ToString("...");
}
Là tốt hơn so với một phương pháp trợ giúp tĩnh bình thường? Tôi nghĩ vậy. Nó làm sạch cú pháp. Thay vì
DateTimeHelper.ToCompanyFormat(myObj.CreatedOn);
Tôi có thể làm:
myObj.CreatedOn.ToCompanyFormat();
Điều này tương tự như một phiên bản lưu loát của cùng một cú pháp. Tôi thích nó hơn, mặc dù không có lợi ích kỹ thuật từ việc có cái này hơn cái kia.
Tất cả những lập luận này là chủ quan. Không ai trong số họ bao gồm một trường hợp có thể không bao giờ được bảo hiểm.
- Mọi phương thức mở rộng có thể dễ dàng được viết lại thành một phương thức tĩnh thông thường.
- Mã có thể được tách trong các tệp bằng các lớp một phần, ngay cả khi các phương thức mở rộng không tồn tại.
Nhưng một lần nữa, chúng ta có thể khẳng định rằng chúng không bao giờ cần thiết đến mức cực đoan:
- Tại sao chúng ta cần các phương thức lớp, nếu chúng ta luôn có thể tạo các phương thức tĩnh với một tên chỉ rõ rằng nó dành cho một lớp cụ thể?
Câu trả lời cho câu hỏi này và của bạn, vẫn như cũ:
- Cú pháp Nicer
- Tăng khả năng đọc và ít mã hơn (mã sẽ đi đến điểm bằng ít ký tự hơn)
- Intellisense cung cấp các kết quả có ý nghĩa theo ngữ cảnh (các phương thức mở rộng chỉ được hiển thị trên đúng loại. Các lớp tĩnh có thể sử dụng ở mọi nơi).
Một đề cập thêm đặc biệt mặc dù:
- Các phương thức mở rộng cho phép một phương thức mã hóa kiểu; gần đây đã trở nên phổ biến hơn, trái ngược với cú pháp gói phương thức vanilla hơn. Các ưu tiên cú pháp tương tự có thể được nhìn thấy trong cú pháp phương thức của LINQ.
- Trong khi chuỗi phương thức có thể được thực hiện bằng cách sử dụng các phương thức lớp; Hãy nhớ rằng điều này không hoàn toàn áp dụng cho các phương thức tĩnh. Các phương thức mở rộng phổ biến nhất dựa trên những thứ mà nếu không phải là phương thức tĩnh, không phải là phương thức lớp.