Tôi đã tự hỏi nếu ai đó có thể cho tôi một cái nhìn tổng quan về lý do tại sao tôi sẽ sử dụng chúng và tôi sẽ đạt được lợi thế gì trong quá trình này.
Tôi đã tự hỏi nếu ai đó có thể cho tôi một cái nhìn tổng quan về lý do tại sao tôi sẽ sử dụng chúng và tôi sẽ đạt được lợi thế gì trong quá trình này.
Câu trả lời:
Việc sử dụng lớn nhất của các lớp một phần là làm cho cuộc sống dễ dàng hơn cho các trình tạo mã / thiết kế. Các lớp một phần cho phép trình tạo đơn giản phát ra mã mà chúng cần phát ra và chúng không phải xử lý các chỉnh sửa của người dùng đối với tệp. Người dùng cũng có thể tự do chú thích lớp với các thành viên mới bằng cách có lớp thứ hai. Điều này cung cấp một khuôn khổ rất sạch để phân tách các mối quan tâm.
Một cách tốt hơn để xem xét nó là để xem các nhà thiết kế hoạt động như thế nào trước các lớp một phần. Nhà thiết kế WinForms sẽ nhổ tất cả các mã bên trong một khu vực với các bình luận mạnh mẽ về việc không sửa đổi mã. Nó đã phải chèn tất cả các loại heuristic để tìm mã được tạo để xử lý sau này. Bây giờ, nó có thể chỉ cần mở tệp designer.cs và có độ tin cậy cao rằng nó chỉ chứa mã có liên quan đến người thiết kế.
Một cách sử dụng khác là phân chia việc thực hiện các giao diện khác nhau, ví dụ:
partial class MyClass : IF1, IF2, IF3
{
// main implementation of MyClass
}
partial class MyClass
{
// implementation of IF1
}
partial class MyClass
{
// implementation of IF2
}
Implements
từ khóa để biểu thị một phương thức thuộc về giao diện)
Ngoài những câu trả lời khác ...
Tôi đã thấy chúng hữu ích như một bước đệm trong việc tái cấu trúc các lớp thần. Nếu một lớp có nhiều trách nhiệm (đặc biệt nếu đó là một tệp mã rất lớn) thì tôi thấy có ích khi thêm 1 phần trách nhiệm cho mỗi lớp một lần đầu tiên để tổ chức và sau đó tái cấu trúc mã.
Điều này giúp ích rất nhiều vì nó có thể giúp làm cho mã dễ đọc hơn nhiều mà không thực sự ảnh hưởng đến hành vi thực thi. Nó cũng có thể giúp xác định khi nào một trách nhiệm dễ dàng tái cấu trúc hoặc bị rối với các khía cạnh khác.
Tuy nhiên - để rõ ràng - đây vẫn là mã xấu, khi kết thúc quá trình phát triển, bạn vẫn muốn có một trách nhiệm cho mỗi lớp ( KHÔNG phải mỗi lớp một phần). Nó chỉ là một bước đệm :)
Chỉ khai báo phương thức một phần Ngay cả mã được biên dịch chỉ với khai báo phương thức và nếu việc triển khai phương thức không có trình biên dịch có thể loại bỏ một cách an toàn đoạn mã đó và sẽ không xảy ra lỗi thời gian biên dịch.
Để xác minh điểm 4. Chỉ cần tạo dự án winform và đưa dòng này vào sau Trình xây dựng Form1 và thử biên dịch mã
partial void Ontest(string s);
Dưới đây là một số điểm cần xem xét khi triển khai các lớp một phần: -
Một cách sử dụng tuyệt vời là tách mã được tạo ra khỏi mã viết tay thuộc cùng một lớp.
Ví dụ, vì LINQ to SQL sử dụng các lớp một phần, bạn có thể tự viết triển khai một số chức năng nhất định (như các mối quan hệ Nhiều-nhiều) và các đoạn mã tùy chỉnh đó sẽ không bị ghi đè khi bạn tạo lại mã.
Điều tương tự cũng xảy ra với mã WinForms. Tất cả các mã do Nhà thiết kế tạo ra sẽ nằm trong một tệp mà bạn thường không chạm vào. Mã viết tay của bạn đi trong một tập tin khác. Theo cách đó, khi bạn thay đổi một cái gì đó trong Nhà thiết kế, những thay đổi của bạn sẽ không bị thổi bay.
Đúng là Class Partial được sử dụng trong việc tạo mã tự động, một lần sử dụng có thể duy trì một tệp lớp lớn có thể có hàng nghìn dòng mã. Bạn không bao giờ biết lớp của bạn có thể kết thúc với 10 nghìn dòng và bạn không muốn tạo một lớp mới với tên khác.
public partial class Product
{
// 50 business logic embedded in methods and properties..
}
public partial class Product
{
// another 50 business logic embedded in methods and properties..
}
//finally compile with product.class file.
Một cách sử dụng khác có thể là nhiều nhà phát triển có thể làm việc trên cùng một lớp khi chúng được lưu trữ ở những nơi khác nhau. Mọi người có thể cười nhưng đôi khi bạn không bao giờ biết nó có thể trở nên khó xử.
public partial class Product
{
//you are writing the business logic for fast moving product
}
public partial class Product
{
// Another developer writing some business logic...
}
Hy vọng nó có ý nghĩa!
Các lớp một phần trải rộng trên nhiều tệp.
Làm thế nào bạn có thể sử dụng công cụ sửa đổi một phần trên khai báo lớp C #?
Với các lớp một phần, bạn có thể tách một lớp thành nhiều tệp. Điều này thường được thực hiện bởi các trình tạo mã.
Thí dụ
Với các lớp C # bình thường, bạn không thể khai báo một lớp trong hai tệp riêng biệt trong cùng một dự án. Nhưng với công cụ partial
sửa đổi, bạn có thể.
Điều này hữu ích nếu một tệp thường được chỉnh sửa và tệp kia được tạo bằng máy hoặc hiếm khi được chỉnh sửa.
Đây là một ví dụ để làm rõ:
class Program
{
static void Main()
{
A.A1();
A.A2();
}
}
Nội dung của tệp A1.cs: C #
using System;
partial class A
{
public static void A1()
{
Console.WriteLine("A1");
}
}
Nội dung của tệp A2.cs: C #
using System;
partial class A
{
public static void A2()
{
Console.WriteLine("A2");
}
}
Đầu ra:
A1
A2
Một phần được yêu cầu ở đây.
Nếu bạn xóa công cụ partial
sửa đổi, bạn sẽ gặp lỗi chứa văn bản này:
[Không gian tên '
<global namespace>
' đã chứa định nghĩa cho 'A
'].
Tiền boa:
Để sửa lỗi này, bạn có thể sử dụng partial
từ khóa hoặc thay đổi một trong các tên lớp.
Trình biên dịch C # xử lý các lớp một phần như thế nào?
Nếu bạn tháo rời chương trình trên (sử dụng IL Disassembler), bạn sẽ thấy các tệp A1.cs và A2.cs bị loại bỏ. Bạn sẽ thấy rằng lớp A có mặt.
Lớp A sẽ chứa các phương thức A1 và A2 trong cùng một khối mã. Hai lớp được hợp nhất thành một.
Kết quả tổng hợp của A1.cs và A2.cs: C #
internal class A
{
// Methods
public static void A1()
{
Console.WriteLine("A1");
}
public static void A2()
{
Console.WriteLine("A2");
}
}
Tóm lược
giữ mọi thứ sạch sẽ nhất có thể khi làm việc với các lớp lớn hoặc khi làm việc nhóm, bạn có thể chỉnh sửa mà không ghi đè (hoặc luôn cam kết thay đổi)
Nếu bạn có một lớp đủ lớn mà không cho vay để tái cấu trúc hiệu quả, việc tách nó thành nhiều tệp sẽ giúp mọi thứ được tổ chức.
Ví dụ: nếu bạn có cơ sở dữ liệu cho một trang chứa diễn đàn thảo luận và hệ thống sản phẩm và bạn không muốn tạo hai lớp nhà cung cấp khác nhau (KHÔNG giống như một lớp proxy, chỉ cần rõ ràng), bạn có thể rõ ràng tạo một lớp một phần trong các tệp khác nhau, như
MyProvider.cs - logic cốt lõi
MyProvider.Forum.cs - phương pháp liên quan cụ thể đến diễn đàn
MyProvider. Productt.cs - phương pháp cho sản phẩm
Đó chỉ là một cách khác để giữ mọi thứ ngăn nắp.
Ngoài ra, như những người khác đã nói, đó là cách duy nhất để thêm các phương thức vào một lớp được tạo mà không có nguy cơ bị bổ sung của bạn bị phá hủy vào lần tiếp theo khi lớp được tạo lại. Điều này có ích với mã được tạo mẫu (T4), ORM, v.v.
Là một thay thế cho các chỉ thị tiền biên dịch.
Nếu bạn sử dụng các chỉ thị tiền biên dịch (cụ thể là #IF DEBUG
) thì bạn sẽ có một số mã trông có vẻ xen kẽ với mã Phát hành thực tế của bạn.
Bạn có thể tạo một lớp riêng biệt để chứa mã này và bao bọc toàn bộ lớp một phần trong một lệnh hoặc bỏ qua tệp mã đó khỏi việc gửi đến trình biên dịch (thực hiện tương tự).
Tham chiếu dịch vụ là một ví dụ khác trong đó các lớp một phần hữu ích để tách mã được tạo ra khỏi mã do người dùng tạo.
Bạn có thể "mở rộng" các lớp dịch vụ mà không bị ghi đè khi bạn cập nhật tham chiếu dịch vụ.
Một công dụng khác tôi thấy là,
Mở rộng một lớp trừu tượng lớn về logic truy cập dữ liệu,
tôi có nhiều tập tin khác nhau với tên Post.cs, Comment.cs, Pages.cs ...
in Post.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of post..
}
in Comment.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of comment..
}
in Pages.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of Pages..
}
Hầu hết mọi người nhận xét rằng partial
chỉ nên được sử dụng cho một lớp có tệp mã được tạo hoặc cho các giao diện. Tôi không đồng ý, và đây là lý do tại sao.
Ví dụ, hãy xem lớp C # System.Math ... đó là lớp . Tôi sẽ không cố nhồi tất cả hơn 70 phương thức vào cùng một tệp mã. Nó sẽ là một cơn ác mộng để duy trì.
Việc đặt từng phương thức toán học vào các tệp lớp một phần riêng lẻ và tất cả các tệp mã vào một thư mục Math trong dự án, sẽ là tổ chức sạch hơn đáng kể.
Điều tương tự có thể / sẽ đúng với nhiều lớp khác có số lượng lớn chức năng đa dạng. Ví dụ, một lớp để quản lý API PrivateProfile có thể có lợi bằng cách chia thành một tập hợp sạch các tệp lớp một phần trong một thư mục dự án.
Cá nhân, tôi cũng chia những gì hầu hết mọi người gọi là các lớp "người trợ giúp" hoặc "tiện ích" thành các tệp riêng lẻ cho từng phương thức hoặc nhóm chức năng phương thức. Ví dụ, trong một dự án, lớp trình trợ giúp chuỗi có gần 50 phương thức. Đó sẽ là một tệp mã dài khó sử dụng ngay cả khi sử dụng các vùng. Nó dễ dàng hơn đáng kể để duy trì bằng cách sử dụng các tệp lớp một phần riêng lẻ cho mỗi phương thức.
Tôi sẽ chỉ cẩn thận sử dụng các lớp một phần và giữ cho tất cả bố cục tệp mã nhất quán trong suốt dự án khi thực hiện điều này. Chẳng hạn như đặt bất kỳ enum công khai lớp nào và các thành viên riêng của lớp vào một tệp Common.cs hoặc có tên tương tự trong thư mục, thay vì phát tán chúng ra khắp các tệp trừ khi chúng chỉ dành riêng cho tệp một phần mà chúng được chứa trong đó.
Hãy nhớ rằng khi bạn chia một lớp thành các tệp riêng biệt, bạn cũng sẽ mất khả năng sử dụng thanh trình phân tách trình soạn thảo văn bản cho phép bạn xem hai phần khác nhau của một tệp hiện tại.
Các lớp một phần cho phép thêm chức năng vào một chương trình được thiết kế phù hợp chỉ bằng cách thêm các tệp nguồn. Ví dụ, một chương trình nhập tệp có thể được thiết kế để người ta có thể thêm các loại tệp đã biết khác nhau bằng cách thêm các mô-đun xử lý chúng. Ví dụ, trình chuyển đổi loại tệp chính có thể bao gồm một lớp nhỏ:
Lớp công khai một phần zzFileConverterRegistrar Đăng ký sự kiện (ByVal mainConverter là zzFileConverter) Đăng ký phụ Tất cả (ByVal mainConverter là zzFileConverter) Đăng ký RaiseEvent (mainConverter) Kết thúc phụ Lớp cuối
Mỗi mô-đun muốn đăng ký một hoặc nhiều loại trình chuyển đổi tệp có thể bao gồm một số thứ như:
Lớp công khai một phần zzFileConverterRegistrar Đăng ký phụ riêngGif (ByVal mainConverter dưới dạng zzFileConverter) Xử lý Me.Register mainConverter.RegisterConverter ("GIF", GifConverter.NewFactory)) Kết thúc phụ Lớp cuối
Lưu ý rằng lớp trình chuyển đổi tệp chính không bị "lộ" - nó chỉ hiển thị một lớp sơ khai nhỏ mà các mô-đun bổ trợ có thể nối vào. Có một chút rủi ro khi đặt tên xung đột, nhưng nếu thói quen "đăng ký" của mỗi mô-đun bổ trợ được đặt tên theo loại tệp mà nó xử lý, có lẽ chúng không nên gây ra vấn đề. Người ta có thể dán GUID vào tên của chương trình con đăng ký nếu người ta lo lắng về những điều đó.
Chỉnh sửa / Phụ lục Để rõ ràng, mục đích của việc này là cung cấp một phương tiện để nhiều lớp riêng biệt có thể cho một chương trình hoặc lớp chính biết về chúng. Điều duy nhất mà trình chuyển đổi tệp chính sẽ làm với zzFileConverterRegistrar là tạo một thể hiện của nó và gọi phương thức registerAll sẽ kích hoạt sự kiện Đăng ký. Bất kỳ mô-đun nào muốn nối sự kiện đó đều có thể thực thi mã tùy ý để đáp ứng với nó (đó là toàn bộ ý tưởng) nhưng không có bất kỳ mô-đun nào có thể làm bằng cách mở rộng không đúng lớp zzFileConverterRegistrar ngoài việc định nghĩa một phương thức có tên phù hợp với phương thức khác . Chắc chắn một phần mở rộng được viết không chính xác có thể phá vỡ một phần mở rộng được viết không đúng, nhưng giải pháp cho điều đó là cho bất kỳ ai không muốn phần mở rộng của mình bị hỏng chỉ cần viết đúng.
Người ta có thể, không sử dụng các lớp một phần, có một chút mã ở đâu đó trong lớp trình chuyển đổi tệp chính, trông giống như:
RegisterConverter ("GIF", GifConvertor.NewFactory) RegisterConverter ("BMP", BmpConvertor.NewFactory) RegisterConverter ("JPEG", JpegConvertor.NewFactory)
nhưng việc thêm một mô-đun chuyển đổi khác sẽ yêu cầu đi vào phần đó của mã chuyển đổi và thêm trình chuyển đổi mới vào danh sách. Sử dụng các phương thức một phần, điều đó không còn cần thiết nữa - tất cả các bộ chuyển đổi sẽ được bao gồm tự động.
IModule
giao diện?
IModule
, bạn có thể sử dụng một khung công tác plugin như MEF (chỉ một trong số rất nhiều), v.v.
Các lớp một phần gần đây đã giúp kiểm soát nguồn trong đó nhiều nhà phát triển đã thêm vào một tệp trong đó các phương thức mới được thêm vào cùng một phần của tệp (được tự động bởi Resharper).
Những đẩy để git gây ra xung đột hợp nhất. Tôi thấy không có cách nào để nói với công cụ hợp nhất lấy các phương thức mới làm một khối mã hoàn chỉnh.
Các lớp một phần trong khía cạnh này cho phép các nhà phát triển bám vào một phiên bản tệp của họ và chúng ta có thể hợp nhất chúng lại sau này bằng tay.
thí dụ -
Từ MSDN :
1.At thời gian biên dịch, các thuộc tính của định nghĩa kiểu một phần được hợp nhất. Ví dụ, hãy xem xét các tuyên bố sau:
[SerializableAttribute]
partial class Moon { }
[ObsoleteAttribute]
partial class Moon { }
Chúng tương đương với các khai báo sau:
[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }
Sau đây được hợp nhất từ tất cả các định nghĩa loại một phần:
Nhận xét XML
giao diện
thuộc tính tham số kiểu chung
thuộc tính lớp
các thành viên
2. Một điều nữa, các lớp một phần lồng nhau cũng có thể là một phần:
partial class ClassWithNestedClass
{
partial class NestedClass { }
}
partial class ClassWithNestedClass
{
partial class NestedClass { }
}
Dưới đây là danh sách một số lợi thế của các lớp một phần.
Bạn có thể tách mã thiết kế UI và mã logic nghiệp vụ để dễ đọc và dễ hiểu. Ví dụ: bạn đang phát triển một ứng dụng web bằng Visual Studio và thêm một biểu mẫu web mới thì có hai tệp nguồn là "aspx.cs" và "aspx.designer.cs". Hai tệp này có cùng một lớp với từ khóa một phần. Lớp ".aspx.cs" có mã logic nghiệp vụ trong khi "aspx.designer.cs" có định nghĩa điều khiển giao diện người dùng.
Khi làm việc với nguồn được tạo tự động, mã có thể được thêm vào lớp mà không phải tạo lại tệp nguồn. Ví dụ: bạn đang làm việc với LINQ to SQL và tạo tệp DBML. Bây giờ khi bạn kéo và thả một bảng, nó sẽ tạo một lớp một phần trong designer.cs và tất cả các cột trong bảng đều có các thuộc tính trong lớp. Bạn cần thêm các cột trong bảng này để liên kết trên lưới UI nhưng bạn không muốn thêm một cột mới vào bảng cơ sở dữ liệu để bạn có thể tạo một tệp nguồn riêng cho lớp này có thuộc tính mới cho cột đó và nó sẽ là một lớp một phần. Vì vậy, điều đó ảnh hưởng đến ánh xạ giữa bảng cơ sở dữ liệu và thực thể DBML nhưng bạn có thể dễ dàng có được một trường bổ sung. Nó có nghĩa là bạn có thể tự viết mã mà không làm hỏng mã được tạo bởi hệ thống.
Nhiều nhà phát triển có thể đồng thời viết mã cho lớp.
Bạn có thể duy trì ứng dụng của mình tốt hơn bằng cách nén các lớp lớn. Giả sử bạn có một lớp có nhiều giao diện để bạn có thể tạo nhiều tệp nguồn tùy thuộc vào việc thực hiện giao diện. Thật dễ hiểu và duy trì một giao diện được triển khai trên đó tệp nguồn có một lớp một phần.
Bất cứ khi nào tôi có một lớp có chứa một lớp lồng nhau có kích thước / độ phức tạp đáng kể, tôi đánh dấu lớp đó partial
và đặt lớp lồng vào một tệp riêng biệt. Tôi đặt tên cho tệp chứa lớp lồng nhau bằng quy tắc: [tên lớp]. [Tên lớp lồng nhau] .cs.
Blog MSDN sau đây giải thích việc sử dụng các lớp một phần với các lớp lồng nhau để duy trì: http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/USE-partial- classes-with-nested-classes- for- khả năng bảo trì.aspx
Tôi biết câu hỏi này thực sự cũ nhưng tôi chỉ muốn thêm phần của mình vào các lớp học một phần.
Một lý do mà cá nhân tôi sử dụng các lớp một phần là khi tôi tạo các ràng buộc cho một chương trình, đặc biệt là các máy trạng thái.
Ví dụ, OpenGL là một cỗ máy nhà nước, có những đống các phương pháp đó đều có thể được thay đổi trên toàn cầu, tuy nhiên, trong kinh nghiệm của tôi ràng buộc một cái gì đó tương tự như OpenGL nơi có rất nhiều phương pháp, lớp có thể dễ dàng vượt quá 10k LỘC.
Các lớp học một phần sẽ chia nhỏ điều này cho tôi và giúp tôi tìm ra các phương pháp nhanh chóng.
Các lớp một phần chủ yếu được giới thiệu để giúp Trình tạo mã, vì vậy chúng tôi (người dùng) cuối cùng không mất tất cả công việc / thay đổi của chúng tôi đối với các lớp được tạo như lớp .designer.cs của ASP.NET mỗi khi chúng tôi tạo lại, gần như tất cả các công cụ mới tạo mã LINQ, EntityFrameworks, ASP.NET sử dụng các lớp một phần cho mã được tạo, vì vậy chúng ta có thể thêm hoặc thay đổi logic các mã được tạo này một cách an toàn bằng cách sử dụng các lớp và phương thức Partial, nhưng hãy cẩn thận trước khi bạn thêm công cụ vào mã được tạo bằng các lớp Partial Sẽ dễ dàng hơn nếu chúng ta phá vỡ bản dựng nhưng tệ nhất nếu chúng ta giới thiệu lỗi thời gian chạy. Để biết thêm chi tiết, hãy kiểm tra http://www.4guysfromrolla.com/articles/071509-1.aspx
Tôi lưu ý hai cách sử dụng mà tôi không thể tìm thấy rõ ràng trong câu trả lời.
Một số nhà phát triển sử dụng các bình luận để phân tách các "phần" khác nhau của lớp. Ví dụ: một nhóm có thể sử dụng quy ước sau:
public class MyClass{
//Member variables
//Constructors
//Properties
//Methods
}
Với các lớp một phần, chúng ta có thể tiến thêm một bước và chia các phần thành các tệp riêng biệt. Theo quy ước, một nhóm có thể hậu tố mỗi tệp với phần tương ứng với nó. Vì vậy, ở trên, chúng ta sẽ có một cái gì đó như: MyClassMembers.cs, MyClassConstructor.cs, MyClassProperIES.cs, MyClassMethods.cs.
Như các câu trả lời khác đã ám chỉ, việc có nên chia lớp lên hay không có lẽ phụ thuộc vào mức độ lớn của lớp trong trường hợp này. Nếu nó nhỏ, có lẽ dễ dàng hơn để có mọi thứ trong một lớp chính. Nhưng nếu bất kỳ phần nào trong số đó trở nên quá lớn, nội dung của nó có thể được chuyển sang một lớp riêng biệt, để giữ cho lớp chủ gọn gàng. Một quy ước trong trường hợp đó có thể là để lại một bình luận khi nói điều gì đó như "Xem một phần lớp" sau phần tiêu đề, vd:
//Methods - See partial class
Đây có thể là một sự cố hiếm khi xảy ra, nhưng có thể có xung đột không gian tên giữa hai chức năng từ các thư viện mà bạn muốn sử dụng. Trong một lớp duy nhất, nhiều nhất bạn có thể sử dụng mệnh đề sử dụng cho một trong những mệnh đề này. Đối với những người khác, bạn cần một tên đủ điều kiện hoặc bí danh. Với các lớp một phần, do mỗi không gian tên và danh sách câu lệnh sử dụng là khác nhau, người ta có thể tách hai bộ hàm thành hai tệp riêng biệt.
using Library1 = The.Namespace.You.Need
hoặcglobal::Root.Of.Namespace