2011-08-09 42 views
14

我爲可訪問性的初學者會話設置了一些演示代碼,並且發現我能夠從派生類訪問內部受保護屬性。我錯過了什麼?內部受保護的屬性仍可從不同的程序集訪問

組件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(); 
     } 
    } 
} 

組件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); 
     } 
    } 
} 

注意在ExampleClass.Go我可以設置一個值,以Prop5。爲什麼?它被標記爲內部保護,但我不能在Prop4上設置一個值(標記爲內部)

+16

因爲它是*內部*或*保護*。不是。 –

+1

-1:顯然,一個簡單的谷歌搜索將回答這個問題... –

+1

我不認爲這是或者 –

回答

20

internal protected的意思是「內部的程序集或繼承類」。所以,是的,如果你有一個受保護的內部成員一個公共類,繼承在不同的組件類型的其他類仍然可以訪問它,因爲受保護的改性劑:

保護內部

類型或成員可以通過聲明它的程序集中的任何代碼,從另一個程序集的派生類中進行訪問。從另一個程序集進行訪問必須在派生自聲明受保護內部元素的類的類聲明中進行,並且必須通過派生類類型的實例進行。

參考:http://msdn.microsoft.com/en-us/library/ms173121.aspx

這是C#語言的限制。 CLR支持「內部和受保護」的概念。如果您正在發佈自己的IL,則可以通過MethodAttributes.FamANDAssem進行枚舉。如果你真的需要想要這個功能,你可以用Mono.Cecil之類的東西做一些IL後期處理。爲什麼C#語言不公開這只是一個猜測:對它的需求不大。

6

因爲這是internal protected的工作原理。在繼承樹(protected部分)或同一個程序集(internal部分)中給予子女的訪問權 - 見Access Modifiers on MSDN

而您的ExampleClass位於BaseClass的繼承樹中,該樹定義了Prop5。所以訪問得益於protected部分。

+0

我喜歡簡單的解釋。 –

4

通過組合受保護關鍵字和內部關鍵字,類成員可以被標記爲受保護的內部 - 在同一個程序集中只有派生類型或類型才能訪問該成員。

This MSDN article回答你所有的問題。

+0

所以它是或不限於它最受限制的關鍵字? –

+0

這是正確的。受保護的內部意味着派生類型(受保護)和程序集(內部)都可以訪問它。這隻適用於內部修飾符。你不能合併其他人。 –

3

受保護的關鍵字是成員訪問修飾符。受保護的成員可以從聲明該類的類中進行訪問,也可以從派生於聲明該成員的類的任何類中進行訪問。

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

通過結合保護和內部的關鍵字,一個類的成員可以被標記保護的內部 - 僅派生類型或類型相同的組件內可以訪問該構件。

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

2

Protected意味着它僅與子類共享,只有private意味着它不能被其他人訪問。

編輯:漢斯評論讓你的問題更清楚一點。當你將這些修飾符組合在一起時,它們並不完全相同。它可以以各種方式訪問​​internalprotected

0

遲到了,但我陷入了同樣的問題。最終我想出了一個部分解決方案。

internal Int MyInt 
    { 
     get; 
     protected set; 
    } 

它仍然可以在程序集中看到,但至少只有繼承類可以真正改變它。這對我想要的是足夠的。

相關問題