2011-08-09 25 views
14

Tôi đang thiết lập một số mã demo cho phiên mới bắt đầu về khả năng truy cập và tôi thấy rằng tôi có thể truy cập một thuộc tính được bảo vệ nội bộ từ một lớp dẫn xuất. Tôi đang thiếu gì?thuộc tính được bảo vệ nội bộ vẫn có thể truy cập từ một assembly khác nhau

hội 1

namespace Accessibility 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      ExampleClass c = new ExampleClass(); 
      c.Go(); 
      //c.Prop1 = 10; 
     } 
    } 

    class ExampleClass : DerivedClass 
    { 
     public void Go() 
     { 
      this.Prop1 = 10; 
      this.Prop2 = 10; 
      //this.Prop3 = 10; //Doesn't work 
      //this.Prop4 = 10; //Doesn't work 
      this.Prop5 = 10; //why does this work?! 

      this.DoSomething(); 
     } 
    } 
} 

hội 2

namespace Accessibility.Models 
{ 
    public class BaseClass 
    { 
     public int Prop1 { get; set; } 
     protected int Prop2 { get; set; } 
     private int Prop3 { get; set; } 

     internal int Prop4 { get; set; } 
     internal protected int Prop5 { get; set; } 
     //internal public int Prop6 { get; set; } //Invalid 
     //internal private int Prop7 { get; set; } //Invalid 

     public BaseClass() 
     { 
      this.Prop3 = 27; 
     } 
    } 

    public class DerivedClass : BaseClass 
    { 
     public void DoSomething() 
     { 
      this.Prop1 = 10; 
      this.Prop2 = 10; 
      //this.Prop3 = 10; //Doesn't work 
      this.Prop4 = 10; 
      this.Prop5 = 10; 

      PropertyInfo Prop3pi = typeof(DerivedClass).GetProperty("Prop3", BindingFlags.Instance | BindingFlags.NonPublic); 
      int value = (int)Prop3pi.GetValue(this, null); 
     } 
    } 
} 

Lưu ý trong ExampleClass.Go tôi có thể đặt một giá trị để Prop5. Tại sao? Nó được đánh dấu là bảo vệ nội bộ nhưng tôi không thể đặt giá trị trên Prop4 (được đánh dấu là nội bộ)

+16

Vì đó là * nội bộ * HOẶC * được bảo vệ *. Không VÀ. –

+1

-1: Rõ ràng, một tìm kiếm đơn giản trên google sẽ trả lời câu hỏi này ... –

+1

Tôi không nghĩ đó là HOẶC –

Trả lời

20

internal protected có nghĩa là "nội bộ cho hội đồng HOẶC một lớp được kế thừa". Vì vậy, có, nếu bạn có một lớp công chúng với một thành viên nội bộ được bảo vệ, một lớp được thừa kế đó gõ vào một hội đồng khác nhau vẫn có thể truy cập vào nó vì modifier bảo vệ:

bảo vệ nội bộ

Loại hoặc thành viên có thể được truy cập bởi bất kỳ mã nào trong assembly mà nó được khai báo, hoặc từ bên trong một lớp dẫn xuất trong một assembly khác.Việc truy cập từ một assembly khác phải diễn ra trong một khai báo lớp xuất phát từ lớp trong đó phần tử bên trong được bảo vệ được khai báo và nó phải được thực hiện thông qua một cá thể của kiểu lớp dẫn xuất.

tham khảo: http://msdn.microsoft.com/en-us/library/ms173121.aspx

Đây là một hạn chế của ngôn ngữ C#. CLR hỗ trợ khái niệm "Internal AND Protected". Có bằng chứng về điều này với thông số MethodAttributes.FamANDAssem nếu bạn phát ra IL của riêng bạn. Nếu bạn thực sự muốn tính năng này, bạn có thể thực hiện một số xử lý bài đăng của IL bằng một cái gì đó như Mono.Cecil. Tại sao ngôn ngữ C# không phơi bày điều này chỉ là phỏng đoán: ít cần cho nó.

6

Vì đó là cách internal protected được thiết kế để hoạt động. Truy cập được cung cấp cho trẻ em trong cây thừa kế (protected một phần) hoặc cho cùng một cụm (internal một phần) - xem Access Modifiers on MSDN.

ExampleClass của bạn nằm trong cây thừa kế BaseClass, xác định Prop5. Vì vậy, truy cập là nhờ vào protected một phần.

+0

tôi thích lời giải thích đơn giản. –

4

Bằng cách kết hợp từ khóa được bảo vệ và nội bộ, thành viên của lớp có thể được đánh dấu là được bảo vệ nội bộ - chỉ các loại hoặc loại có nguồn gốc trong cùng một hội đồng mới có thể truy cập thành viên đó.

This MSDN article trả lời tất cả câu hỏi của bạn.

+0

Vì vậy, hoặc là, hoặc không giới hạn ở đó là từ khóa bị hạn chế nhất? –

+0

Đúng vậy. Nội bộ được bảo vệ có nghĩa là cả hai loại dẫn xuất (được bảo vệ) và assembly (nội bộ) có thể truy cập nó. Điều đó chỉ áp dụng cho công cụ sửa đổi nội bộ. Bạn không thể kết hợp những người khác. –

3

Từ khóa được bảo vệ là công cụ sửa đổi truy cập thành viên. Một thành viên được bảo vệ có thể truy cập từ bên trong lớp mà nó được khai báo, và từ bên trong bất kỳ lớp nào có nguồn gốc từ lớp đã khai báo thành viên này.

http://msdn.microsoft.com/en-us/library/bcd5672a(v=vs.71).aspx

Bằng cách kết hợp các từ khóa được bảo vệ và bên trong, một thành viên lớp có thể được đánh dấu bảo vệ nội bộ - loại chỉ có nguồn gốc hoặc các loại trong cùng một assembly có thể truy cập thành viên đó.

http://msdn.microsoft.com/en-us/library/ms173121(v=vs.80).aspx

2

Protected có nghĩa là nó được chia sẻ chỉ với các lớp hậu duệ, chỉ private có nghĩa là nó không thể được truy cập bởi bất cứ ai khác.

Chỉnh sửa: Hans nhận xét làm cho câu hỏi của bạn rõ ràng hơn một chút. Khi bạn kết hợp các công cụ sửa đổi như vậy, chúng kết hợp toàn bộ không chỉ riêng. Nó là accesse trong tất cả các cách internal hoặc protected có thể được.

0

Trả lời muộn nhưng tôi bị bắt cùng một vấn đề. Cuối cùng tôi đã đưa ra một giải pháp một phần.

internal Int MyInt 
    { 
     get; 
     protected set; 
    } 

Nó vẫn hiển thị trong hội đồng nhưng ít nhất chỉ các lớp kế thừa mới có thể thay đổi nó. Đó là đủ cho những gì tôi muốn.

Các vấn đề liên quan