Bạn có thể giải thích cách sử dụng thực tế cho internal
từ khóa trong C # không?
Tôi biết rằng công cụ internal
sửa đổi giới hạn quyền truy cập vào hội đồng hiện tại, nhưng tôi nên sử dụng nó khi nào và trong trường hợp nào?
Bạn có thể giải thích cách sử dụng thực tế cho internal
từ khóa trong C # không?
Tôi biết rằng công cụ internal
sửa đổi giới hạn quyền truy cập vào hội đồng hiện tại, nhưng tôi nên sử dụng nó khi nào và trong trường hợp nào?
Câu trả lời:
Các lớp / phương thức của trình trợ giúp hoặc tiện ích mà bạn muốn truy cập từ nhiều lớp khác trong cùng một cụm, nhưng bạn muốn đảm bảo mã trong các cụm khác không thể truy cập.
Từ MSDN (thông qua archive.org):
Việc sử dụng phổ biến truy cập nội bộ là trong phát triển dựa trên thành phần vì nó cho phép một nhóm các thành phần hợp tác theo cách riêng tư mà không bị lộ với phần còn lại của mã ứng dụng. Ví dụ, một khung để xây dựng giao diện người dùng đồ họa có thể cung cấp các lớp Điều khiển và Biểu mẫu hợp tác sử dụng các thành viên có quyền truy cập nội bộ. Vì các thành viên này là nội bộ, họ không được tiếp xúc với mã đang sử dụng khung.
Bạn cũng có thể sử dụng công cụ sửa đổi nội bộ cùng với InternalsVisibleTo
thuộc tính cấp độ lắp ráp để tạo các cụm "bạn bè" được cấp quyền truy cập đặc biệt vào các lớp bên trong lắp ráp đích.
Điều này có thể hữu ích cho việc tạo ra các hội đồng thử nghiệm đơn vị mà sau đó được phép gọi các thành viên nội bộ của hội đồng sẽ được thử nghiệm. Tất nhiên không có hội đồng nào khác được cấp mức truy cập này, vì vậy khi bạn phát hành hệ thống của mình, việc đóng gói được duy trì.
Nếu Bob cần BigImportantClass thì Bob cần phải nhờ những người sở hữu dự án A đăng ký để đảm bảo rằng BigImportantClass sẽ được viết để đáp ứng nhu cầu của anh ta, được kiểm tra để đảm bảo đáp ứng nhu cầu của anh ta, được ghi nhận là đáp ứng nhu cầu của anh ta, và đó là một quá trình sẽ được đưa ra để đảm bảo rằng nó sẽ không bao giờ bị thay đổi để không còn đáp ứng nhu cầu của anh ta nữa.
Nếu một lớp là nội bộ thì nó không phải trải qua quá trình đó, giúp tiết kiệm ngân sách cho Dự án A mà họ có thể chi cho những thứ khác.
Quan điểm của nội bộ không phải là nó làm cho cuộc sống của Bob trở nên khó khăn. Đó là nó cho phép bạn kiểm soát những lời hứa đắt giá mà Project A đang thực hiện về các tính năng, tuổi thọ, khả năng tương thích, v.v.
Một lý do khác để sử dụng nội bộ là nếu bạn làm xáo trộn nhị phân của mình. Obfuscator biết rằng an toàn khi xáo trộn tên lớp của bất kỳ lớp bên trong nào, trong khi tên của các lớp công khai không thể bị xáo trộn, vì điều đó có thể phá vỡ các tham chiếu hiện có.
Nếu bạn đang viết một DLL đóng gói một tấn chức năng phức tạp vào một API công khai đơn giản, thì nội bộ của Cameron được sử dụng cho các thành viên lớp không được công khai.
Ẩn sự phức tạp (hay còn gọi là đóng gói) là khái niệm chính của công nghệ phần mềm chất lượng.
Từ khóa nội bộ được sử dụng nhiều khi bạn đang xây dựng một trình bao bọc cho mã không được quản lý.
Khi bạn có thư viện dựa trên C / C ++ mà bạn muốn DLLImport, bạn có thể nhập các hàm này dưới dạng hàm tĩnh của một lớp và biến chúng thành nội bộ, vì vậy người dùng của bạn chỉ có quyền truy cập vào trình bao bọc của bạn chứ không phải API gốc để không thể lộn xộn với bất cứ điều gì. Các hàm là tĩnh bạn có thể sử dụng chúng ở mọi nơi trong cụm, cho nhiều lớp bao bọc bạn cần.
Bạn có thể xem Mono.Cairo, đây là một trình bao bọc xung quanh thư viện cairo sử dụng phương pháp này.
Được điều khiển bởi "sử dụng công cụ sửa đổi nghiêm ngặt như bạn có thể" quy tắc Tôi sử dụng nội bộ ở mọi nơi tôi cần truy cập, giả sử, phương thức từ một lớp khác cho đến khi tôi rõ ràng cần truy cập nó từ một hội đồng khác.
Vì giao diện lắp ráp thường hẹp hơn so với tổng các giao diện lớp của nó, có khá nhiều nơi tôi sử dụng nó.
Tôi thấy nội bộ được sử dụng quá mức. bạn thực sự không nên chỉ hiển thị một số chức năng nhất định cho các lớp nhất định mà bạn sẽ không cho người tiêu dùng khác.
Điều này theo tôi phá vỡ giao diện, phá vỡ sự trừu tượng. Điều này không có nghĩa là không bao giờ nên sử dụng nó, nhưng một giải pháp tốt hơn là tái cấu trúc sang một lớp khác hoặc được sử dụng theo một cách khác nếu có thể. Tuy nhiên, điều này có thể không phải lúc nào cũng có thể.
Những lý do nó có thể gây ra vấn đề là nhà phát triển khác có thể bị buộc tội xây dựng một lớp khác trong cùng một tổ hợp mà bạn đang có. Có nội bộ làm giảm sự rõ ràng của sự trừu tượng, và có thể gây ra vấn đề nếu bị lạm dụng. Nó sẽ là vấn đề tương tự như khi bạn công khai nó. Lớp khác đang được xây dựng bởi nhà phát triển khác vẫn là người tiêu dùng, giống như bất kỳ lớp bên ngoài nào. Trừu tượng hóa lớp và đóng gói không chỉ để bảo vệ cho / từ các lớp bên ngoài, mà cho bất kỳ và tất cả các lớp.
Một vấn đề khác là rất nhiều nhà phát triển sẽ nghĩ rằng họ có thể cần phải sử dụng nó ở nơi khác trong hội đồng và đánh dấu nó là dù sao đi nữa, mặc dù lúc đó họ không cần đến nó. Một nhà phát triển khác sau đó có thể nghĩ rằng nó có để lấy. Thông thường bạn muốn đánh dấu riêng tư cho đến khi bạn có một nhu cầu dứt khoát.
Nhưng một số điều này có thể chủ quan, và tôi không nói rằng nó không bao giờ nên được sử dụng. Chỉ cần sử dụng khi cần thiết.
Tôi thấy một điều thú vị vào một ngày khác, có thể là tuần, trên một blog mà tôi không thể nhớ. Về cơ bản tôi không thể tin tưởng vào điều này nhưng tôi nghĩ nó có thể có một số ứng dụng hữu ích.
Giả sử bạn muốn một lớp trừu tượng được nhìn thấy bởi một hội đồng khác nhưng bạn không muốn ai đó có thể kế thừa từ nó. Bịt kín sẽ không hoạt động vì nó trừu tượng vì một lý do, các lớp khác trong hội đồng đó được thừa hưởng từ nó. Riêng tư sẽ không hoạt động vì bạn có thể muốn khai báo một lớp Parent ở đâu đó trong hội đồng khác.
không gian tên Base.Assugging { lớp trừu tượng công cộng Phụ huynh { khoảng trống trừu tượng bên trong someMethod (); } // Điều này hoạt động tốt vì nó trong cùng một hội đồng. lớp học công cộng ChildWithin: Phụ huynh { ghi đè nội bộ void someMethod () { } } } không gian tên Another.Assugging { // Kaboom, vì bạn không thể ghi đè một phương thức nội bộ lớp học công cộng ChildOutside: Phụ huynh { } Kiểm tra lớp học công cộng { //Bình thường Cha mẹ riêng _parent; Kiểm tra công khai () { //Vẫn khỏe _parent = new ChildWithin (); } } }
Như bạn có thể thấy, nó thực sự cho phép ai đó sử dụng lớp Parent mà không thể kế thừa từ đó.
Ví dụ này chứa hai tệp: Hội1.cs và Hội2.cs. Tệp đầu tiên chứa một lớp cơ sở nội bộ, BaseClass. Trong tệp thứ hai, một nỗ lực khởi tạo BaseClass sẽ tạo ra lỗi.
// Assembly1.cs
// compile with: /target:library
internal class BaseClass
{
public static int intM = 0;
}
// Assembly1_a.cs
// compile with: /reference:Assembly1.dll
class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // CS0122
}
}
Trong ví dụ này, sử dụng cùng các tệp bạn đã sử dụng trong ví dụ 1 và thay đổi mức độ truy cập của BaseClass thành công khai . Đồng thời thay đổi mức độ truy cập của IntM thành viên thành nội bộ . Trong trường hợp này, bạn có thể khởi tạo lớp, nhưng bạn không thể truy cập thành viên nội bộ.
// Assembly2.cs
// compile with: /target:library
public class BaseClass
{
internal static int intM = 0;
}
// Assembly2_a.cs
// compile with: /reference:Assembly1.dll
public class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // Ok.
BaseClass.intM = 444; // CS0117
}
}
nguồn : http://msdn.microsoft.com/en-us/l Library / 7c5ka91b (VS.80) .aspx
Khi bạn có các phương thức, các lớp, v.v ... cần truy cập trong phạm vi của hội đồng hiện tại và không bao giờ nằm ngoài nó.
Ví dụ, một DAL có thể có ORM nhưng các đối tượng không được tiếp xúc với lớp nghiệp vụ, tất cả các tương tác phải được thực hiện thông qua các phương thức tĩnh và truyền vào các tham số cần thiết.
Một cách sử dụng nội bộ rất thú vị - tất nhiên với thành viên nội bộ chỉ bị giới hạn trong hội đồng mà nó được tuyên bố - sẽ nhận được chức năng "bạn bè" ở một mức độ nào đó. Một thành viên bạn bè là một cái gì đó chỉ có thể nhìn thấy đối với một số hội đồng khác bên ngoài hội đồng mà nó tuyên bố. C # không có hỗ trợ tích hợp cho bạn bè, tuy nhiên CLR thì có.
Bạn có thể sử dụng InternalsVisibleToAttribution để khai báo hội đồng bạn bè và tất cả các tham chiếu từ bên trong hội đồng bạn bè sẽ coi các thành viên nội bộ của hội đồng khai báo của bạn là công khai trong phạm vi của hội nghị bạn bè. Một vấn đề với điều này là tất cả các thành viên nội bộ có thể nhìn thấy được; bạn không thể chọn và chọn.
Một cách sử dụng tốt cho InternalsVisibleTo là đưa các thành viên nội bộ khác nhau đến một tổ hợp thử nghiệm đơn vị, do đó loại bỏ các nhu cầu về công việc phản xạ phức tạp xung quanh để kiểm tra các thành viên đó. Tất cả các thành viên nội bộ có thể nhìn thấy không phải là vấn đề quá lớn, tuy nhiên thực hiện phương pháp này sẽ làm hỏng giao diện lớp của bạn khá nhiều và có khả năng phá hỏng sự đóng gói trong hội đồng khai báo.
Theo quy tắc, có hai loại thành viên:
Các lớp bên trong cho phép bạn giới hạn API của hội đồng của bạn. Điều này có lợi ích, như làm cho API của bạn đơn giản hơn để hiểu.
Ngoài ra, nếu một lỗi tồn tại trong lắp ráp của bạn, sẽ có ít khả năng sửa lỗi giới thiệu một thay đổi đột phá. Nếu không có các lớp nội bộ, bạn sẽ phải cho rằng việc thay đổi bất kỳ thành viên nào của lớp sẽ là một thay đổi đột phá. Với các lớp bên trong, bạn có thể giả định rằng sửa đổi các thành viên công khai của họ chỉ phá vỡ API nội bộ của hội đồng (và bất kỳ hội đồng nào được tham chiếu trong thuộc tính InternalsVisibleTo).
Tôi thích có sự đóng gói ở cấp độ lớp và ở cấp độ lắp ráp. Có một số người không đồng ý với điều này, nhưng thật tuyệt khi biết rằng chức năng này có sẵn.
Tôi có một dự án sử dụng LINQ-to-SQL cho back-end dữ liệu. Tôi có hai không gian tên chính: Biz và Dữ liệu. Mô hình dữ liệu LINQ sống trong Dữ liệu và được đánh dấu là "nội bộ"; không gian tên Biz có các lớp công khai bao quanh các lớp dữ liệu LINQ.
Vì vậy, có Data.Client
, và Biz.Client
; cái sau phơi bày tất cả các thuộc tính có liên quan của đối tượng dữ liệu, ví dụ:
private Data.Client _client;
public int Id { get { return _client.Id; } set { _client.Id = value; } }
Các đối tượng Biz có một hàm tạo riêng (để buộc sử dụng các phương thức của nhà máy) và một hàm tạo bên trong trông như thế này:
internal Client(Data.Client client) {
this._client = client;
}
Điều đó có thể được sử dụng bởi bất kỳ lớp nghiệp vụ nào trong thư viện, nhưng giao diện người dùng (UI) không có cách nào truy cập trực tiếp vào mô hình dữ liệu, đảm bảo rằng lớp nghiệp vụ luôn hoạt động như một trung gian.
Đây là lần đầu tiên tôi thực sự sử dụng internal
nhiều và nó tỏ ra khá hữu ích.
Có những trường hợp có ý nghĩa để làm cho các thành viên của các lớp internal
. Một ví dụ có thể là nếu bạn muốn kiểm soát cách các lớp được khởi tạo; giả sử bạn cung cấp một số loại nhà máy để tạo các thể hiện của lớp. Bạn có thể tạo hàm tạo internal
, để nhà máy (nằm trong cùng một tổ hợp) có thể tạo các thể hiện của lớp, nhưng mã bên ngoài cụm đó thì không thể.
Tuy nhiên, tôi không thể thấy bất kỳ điểm nào với việc tạo ra các lớp học hoặc thành viên internal
mà không có lý do cụ thể, chỉ cần tạo ra chúng public
hoặc private
không có lý do cụ thể.
điều duy nhất tôi từng sử dụng từ khóa nội bộ là mã kiểm tra giấy phép trong sản phẩm của mình ;-)
Một cách sử dụng từ khóa nội bộ là để hạn chế quyền truy cập vào các triển khai cụ thể từ người dùng lắp ráp của bạn.
Nếu bạn có một nhà máy hoặc một số vị trí trung tâm khác để xây dựng các đối tượng, người dùng lắp ráp của bạn chỉ cần xử lý giao diện chung hoặc lớp cơ sở trừu tượng.
Ngoài ra, các hàm tạo bên trong cho phép bạn kiểm soát vị trí và khi nào một lớp công khai được khởi tạo.
Làm thế nào về điều này: thông thường, bạn không nên để lộ một đối tượng Danh sách cho người dùng bên ngoài của một hội đồng, thay vào đó để lộ một IEnumerable. Nhưng việc sử dụng một đối tượng List bên trong assembly sẽ dễ dàng hơn nhiều, bởi vì bạn có được cú pháp mảng và tất cả các phương thức List khác. Vì vậy, tôi thường có một thuộc tính nội bộ hiển thị Danh sách sẽ được sử dụng bên trong hội đồng.
Bình luận được hoan nghênh về phương pháp này.
Hãy nhớ rằng bất kỳ lớp nào được xác định là public
sẽ tự động hiển thị trong intellisense khi ai đó nhìn vào không gian tên dự án của bạn. Từ góc độ API, điều quan trọng là chỉ hiển thị cho người dùng dự án của bạn các lớp mà họ có thể sử dụng. Sử dụng internal
từ khóa để ẩn những thứ họ không nên thấy.
Nếu Big_Important_Class
dự án A của bạn được dự định sử dụng bên ngoài dự án của bạn, thì bạn không nên đánh dấu nó internal
.
Tuy nhiên, trong nhiều dự án, bạn sẽ thường có các lớp thực sự chỉ dành cho sử dụng bên trong một dự án. Ví dụ, bạn có thể có một lớp chứa các đối số cho một lời gọi luồng được tham số hóa. Trong những trường hợp này, bạn nên đánh dấu chúng như internal
thể không vì lý do nào khác ngoài việc bảo vệ bản thân khỏi sự thay đổi API ngoài ý muốn.
private
từ khóa chỉ có thể được sử dụng trên lớp hoặc cấu trúc được định nghĩa trong một lớp học hoặc struct. Một lớp được định nghĩa trong một không gian tên chỉ có thể được khai báo public
hoặc internal
.
Ý tưởng là khi bạn thiết kế một thư viện, chỉ các lớp được dự định sử dụng từ bên ngoài (bởi các khách hàng của thư viện của bạn) nên được công khai. Bằng cách này bạn có thể ẩn các lớp
Vân vân.
Nếu bạn đang phát triển các giải pháp đường phố hơn là sử dụng các yếu tố nội bộ thì tôi đoán không quan trọng, bởi vì thông thường các khách hàng sẽ liên lạc thường xuyên với bạn và / hoặc truy cập vào mã. Họ là khá quan trọng cho các nhà phát triển thư viện mặc dù.
Khi bạn có các lớp hoặc phương thức không phù hợp với Mô hình hướng đối tượng, thực hiện các công cụ nguy hiểm, cần được gọi từ các lớp và phương thức khác dưới sự kiểm soát của bạn và bạn không muốn cho phép bất kỳ ai khác sử dụng .
public class DangerousClass {
public void SafeMethod() { }
internal void UpdateGlobalStateInSomeBizarreWay() { }
}