Khi nào thì thích hợp để sử dụng các lớp một phần C #?


Câu trả lời:


423

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ế.


70
Bị cám dỗ mang đến cho bạn -1 vì đã cho tôi những cơn ác mộng về những điều tồi tệ như thế nào trước các lớp học một phần :)
Jon B

9
@Jon :), tôi nghĩ tất cả chúng ta đều có những cơn ác mộng.
JaredPar

18
Khi tôi đã viết một trình tạo mã tạo ra hơn 36K dòng (hoặc có thể nhiều hơn nữa, tôi không nhớ chính xác) và các trình soạn thảo của tôi đã bị chặn khi nguồn được mở. Các lớp một phần cho phép tôi xem mã được sản xuất mà không cần 4 GB RAM.
Luca

6
Tôi đã đi xa để nói rằng đây là cách sử dụng duy nhất cho các lớp một phần trong mã sản xuất. Mặc dù tôi chấp nhận nó có thể hữu ích cho việc tái cấu trúc.
Gordon McAllister

5
@Gordon - Câu trả lời của HumerGu là một câu hỏi khác mà tôi nghĩ là khá khó để tranh luận. Các lớp một phần có thể rất thuận tiện để triển khai các giao diện trong C # và giữ cho các thành viên giao diện tách biệt rõ ràng với các thành viên của lớp: stackoverflow.com/questions/3601901/why-use-partial-
classes / từ

262

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
}

6
Điểm tốt! Đó là điều tôi đã làm trước đây và quên đi, nhưng chắc chắn là một cách hay để giữ cho các thành viên giao diện hiển thị rõ ràng (đặc biệt là trong C #, vì VB.NET sử dụng Implementstừ khóa để biểu thị một phương thức thuộc về giao diện)
STW

2
Điểm rất hay, mỗi giao diện có thể được Nhà phát triển triển khai, Ngoài ra, đó là cách tốt để tìm cách triển khai giao diện một cách dễ dàng.
kokabi

3
Làm thế nào để người ta biết cái nào dành cho IF1 hoặc IF2 .. theo thứ tự khai báo các lớp?
kuldeep

17
Một sử dụng tốt nhưng một ví dụ xấu. Tại sao oh tại sao bạn lại định nghĩa tất cả các giao diện trên một lớp một phần và triển khai các giao diện tương tự trong các lớp một phần khác? ..
inkredibl

4
Ha, tôi chỉ tra cứu câu hỏi này để xem việc tách biệt các triển khai giao diện có phải là cách sử dụng tiêu chuẩn cho các lớp một phần không. Vui mừng khi thấy rằng những người khác xem nó là một ý tưởng tốt. Tôi đồng ý với @inkredibl về việc đặt định nghĩa giao diện cùng với lớp một phần thực hiện nó.
Kim

172

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 :)


23
Rất hay: "... 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) ..."
kokabi

Đối với tôi, nó không phải là một phong cách mã hóa tốt, nhưng có thể làm cho các mã xấu trông tốt hơn.
quả vào

Tôi hoàn toàn đồng ý. Đó là một bước đệm tốt để sửa mã xấu. Một lớp thần là thời tiết của lớp thần, nó có trải đều trên nhiều tệp hay không.
Jimbo

84
  1. Nhiều nhà phát triển sử dụng các lớp một phần Nhiều nhà phát triển có thể làm việc trên cùng một lớp một cách dễ dàng.
  2. Trình tạo mã Các lớp một phần chủ yếu được sử dụng bởi trình tạo mã để tách các mối quan tâm khác nhau
  3. Các phương thức một phần bằng cách sử dụng các lớp một phần, bạn cũng có thể định nghĩa các phương thức một phần cũng như nơi mà nhà phát triển có thể chỉ cần xác định phương thức và nhà phát triển khác có thể thực hiện điều đó.
  4. 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: -

  1. Sử dụng một phần từ khóa trong mỗi phần của một phần lớp.
  2. Tên của từng phần của lớp một phần phải giống nhau nhưng tên tệp nguồn cho mỗi phần của lớp một phần có thể khác nhau.
  3. Tất cả các phần của một lớp một phần phải nằm trong cùng một không gian tên.
  4. Mỗi phần của một lớp một phần phải nằm trong cùng một cụm hoặc DLL, nói cách khác, bạn không thể tạo một lớp một phần trong các tệp nguồn từ một dự án thư viện lớp khác.
  5. Mỗi phần của một phần lớp phải có cùng khả năng truy cập. (tức là: riêng tư, công cộng hoặc được bảo vệ)
  6. Nếu bạn kế thừa một lớp hoặc giao diện trên một lớp một phần thì nó được kế thừa bởi tất cả các phần của lớp một phần đó.
  7. Nếu một phần của một phần của lớp được niêm phong thì toàn bộ lớp sẽ được niêm phong.
  8. Nếu một phần của lớp một phần là trừu tượng thì toàn bộ lớp sẽ được coi là một lớp trừu tượng.

1
Có bất kỳ vấn đề chỉnh sửa một lớp một phần được tạo từ Entity Framework không? Tôi muốn thay đổi một số tên lớp, được tạo từ một bảng.
MarceloBarbosa

Tôi có cùng mối quan tâm. Tôi muốn biết những lợi ích "Nếu có" mà một phần lớp có được khi xây dựng các mô hình mà Entity Framework về cơ bản sẽ sử dụng để xây dựng cơ sở dữ liệu của tôi từ quan điểm / cách tiếp cận / triển khai Code First ... bạn có gì.
Chef_Code

@JimBalter Vui lòng truy cập liên kết này msdn.microsoft.com/en-us/l Library / 6b0scde8 (v = vs.110) .aspx . Điều này nói rằng nếu không có trình biên dịch hiện tại sẽ loại bỏ đoạn mã và không nhận được lỗi thời gian biên dịch.
hellowahab

Nếu bạn kế thừa một lớp hoặc giao diện trên một lớp một phần thì nó được kế thừa bởi tất cả các phần của lớp một phần đó.
Hạt đậu đỏ

56

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.


21

Đú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ử.

Sản phẩm1.cs

public partial class Product
{
    //you are writing the business logic for fast moving product
}

Sản phẩm2.cs

public partial class Product
{
    // Another developer writing some business logic...
}

Hy vọng nó có ý nghĩa!


13

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ụ partialsử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ụ partialsử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 partialtừ 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

  • Các lớp một phần có thể đơn giản hóa các tình huống lập trình C # nhất định.
  • Chúng thường được sử dụng trong Visual Studio khi tạo các chương trình Windows Forms / WPF.
  • Mã C # do máy tạo là riêng biệt.
  • Hoặc bạn có thể tìm thấy toàn bộ mô tả ở đây .

2
Ví dụ đẹp và tài liệu tốt.
Chef_Code

1
Đây là lời giải thích dễ nhất để làm theo imo.
Yusha

12

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)


11

Việc sử dụng chính cho các lớp một phần là với mã được tạo. Nếu bạn nhìn vào mạng WPF (Windows Presentation Foundation), bạn xác định UI của mình bằng đánh dấu (XML). Đánh dấu đó được biên dịch thành các lớp một phần. Bạn điền mã với các lớp một phần của riêng bạn.


8

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.


2
Tôi sẽ ủng hộ một phần như một bước đệm hướng tới tái cấu trúc (toàn bộ câu trả lời của tôi), nhưng sẽ không đề xuất chúng như một giải pháp thực tế để viết mã sạch. Nếu một lớp một phần được tách biệt rõ ràng khỏi các mối quan tâm khác của lớp, thì tại sao bạn không nỗ lực hết sức để thúc đẩy nó thành một lớp độc lập?
STW

@STW: Có thể có nhiều phiên bản đối tượng được tạo và sử dụng cho các tác vụ khác nhau. Việc tách các nhiệm vụ khác nhau thành các lớp khác nhau sẽ yêu cầu theo dõi những trường hợp nào được sử dụng cho nhiệm vụ nào - có khả năng thực hiện lớn hơn nhiều so với việc chỉ di chuyển các khối mã giữa các mô-đun nguồn.
supercat

4
@supercat - Tôi hiểu hoàn toàn, nhưng nên làm sạch loại mì spaghetti đó . Tôi đã có rất nhiều vết sẹo từ việc làm sạch chính xác loại mã đó và sẽ không bao giờ ủng hộ việc bỏ lại nó. Những loại mớ hỗn độn đó được đảm bảo để liên tục tạo ra các vấn đề, và mức chi trả dài hạn là rất lớn so với việc bỏ qua vấn đề. Mã như thế không "ngửi", nó như một bãi rác.
STW

1
@supercat - Tôi đã cố gắng đủ điều kiện rằng với "Nếu một phần được tách biệt rõ ràng với các mối quan tâm khác ... thì đó là một nỗ lực nhỏ". Vượt qua nỗi đau của việc gỡ rối thường sẽ tiết kiệm lớn trong bảo trì dài hạn, nếu không phải là Rogaine
STW

2
Ngẫu nhiên, tôi đang chơi xung quanh với việc cố gắng sửa đổi Roslyn những ngày này, và nó được viết với việc sử dụng rộng rãi các lớp một phần. Rất nhiều và rất nhiều các lớp chính trong Roslyn được định nghĩa là các lớp một phần trong nhiều tệp. Và Roslyn được viết bởi những người mà tôi, ít nhất, coi là những lập trình viên C # rất thông minh.
RenniePet

8

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ự).


Monogame sử dụng chiến lược này.
Zamboni

6

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ụ.


6

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..
}

6

Hầu hết mọi người nhận xét rằng partialchỉ 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.


4

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.


nó hoạt động, nhưng một hệ thống plugin đơn giản để tải động các mô-đun này sẽ đẹp hơn nhiều và sẽ giúp loại bỏ nguy cơ các mô-đun làm hỏng lẫn nhau (nó có thể tải các mô-đun trong thời gian chạy thay vì yêu cầu biên dịch lại)
STW

Nguy cơ các mô-đun làm hỏng lẫn nhau có thể được giảm thiểu khá tốt nếu chúng không làm gì với lớp zz_ ngoại trừ móc một sự kiện Đăng ký và gọi một thói quen để tự đăng ký. Những rủi ro nào bạn thấy rằng sẽ không tồn tại với một trình cắm thêm? Plug-in rất tuyệt nếu người dùng cuối dự kiến ​​sẽ "cắm" các mô-đun mới. Đôi khi, mặc dù, người ta muốn đặt tất cả các chức năng trong một exe duy nhất. Có thể cắm các tệp nguồn mà không cần phải thêm tham chiếu thủ công vào các tệp mới được thêm vào có thể tiện dụng.
supercat

1
rủi ro được chứa khá nhiều trong dòng của bạn "... nếu họ không làm gì [...] ngoại trừ ...", bảo mật và sự ổn định hoàn toàn thuộc về nhà phát triển theo quy ước và đảm bảo 0%. Nếu trường hợp sử dụng của bạn là để chúng được biên dịch (hoàn toàn hợp lệ, chỉ cần là sự đánh đổi lương tâm) thì tại sao không chỉ có các mô-đun được định nghĩa trong các lớp riêng biệt và thực hiện một số IModulegiao diện?
STW

Nghe có vẻ như một trường hợp "thông minh" trở nên tồi tệ. Đây không phải là "mô-đun", chúng là một lớp duy nhất với nhiều hành vi và trách nhiệm được đưa vào một trong thời gian biên dịch. Có rất nhiều cách tốt hơn để làm điều này - bạn có thể sử dụng Reflection để quét tập hợp đã biên dịch cho các lớp thực hiệ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.
STW

3

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ụ -

  • MainClass.cs - giữ các trường, hàm tạo, v.v.
  • MainClass1.cs - một nhà phát triển mã mới khi họ triển khai
  • MainClass2.cs - là một lớp nhà phát triển khác cho mã mới của họ.

3

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 { }
}

1

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.


1

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 đó partialvà đặ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


1

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 giúp tôi tìm ra các phương pháp nhanh chóng.


0

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


0

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.

Nhóm các mục lớp

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

Quản lý phạm vi sử dụng câu lệnh / Không gian tên

Đâ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.


Có các cơ chế để giải quyết xung đột không gian tên, ví dụ, đổi tên một không gian tên bằng cách sử dụng using Library1 = The.Namespace.You.Needhoặcglobal::Root.Of.Namespace
fjch1997

Vâng, tôi cho rằng đó là một trường hợp sử dụng yếu. Nhưng nó đẹp hơn một chút để không phải đủ điều kiện tên. Nhiều hơn một tác dụng phụ ngoài ý muốn tốt hơn là một lý do cho việc sử dụng các lớp một phần.
Colm Bhandal
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.