Внутреннее защищенное свойство, доступное из другой сборки

Я создаю демо-код для начального сеанса по доступности, и я обнаружил, что я могу получить доступ к внутреннему защищенному свойству из производного класса. Что мне не хватает?

Сборка 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);
        }
    }
}

Обратите внимание, что в примереClass.Go я могу установить значение Prop5. Зачем? Он помечен как внутренний, но я не могу установить значение на Prop4 (помечено как внутреннее)

Ответы

Ответ 1

internal protected означает "внутреннее для сборки или унаследованный класс". Так что да, если у вас есть открытый класс с защищенным внутренним членом, другой класс, который наследует этот тип в другой сборке, может получить к нему доступ из-за защищенного модификатора:

защищенный внутренний

Доступ к типу или члену может получить любой код в сборке, в котором он объявлен, или из производного класса в другой сборке. Доступ из другой сборки должен происходить в объявлении класса, которое происходит от класса, в котором объявлен защищенный внутренний элемент, и он должен выполняться через экземпляр типа производного класса.

Ссылка: http://msdn.microsoft.com/en-us/library/ms173121.aspx

Это ограничение языка С#. CLR поддерживает понятие "Внутреннее и защищенное". Это свидетельствует об этом с перечислением MethodAttributes.FamANDAssem, если вы излучали свой собственный IL. Если вам действительно нужна эта функция, вы можете выполнить некоторую обработку сообщений IL с помощью чего-то вроде Mono.Cecil. Почему язык С# не раскрывает это, это только предположение: мало нужно для него.

Ответ 2

Потому что он как internal protected предназначен для работы. Доступ предоставляется для детей в дереве наследования (protected part) или для той же сборки (internal part) - см. Модификаторы доступа в MSDN.

И ваш ExampleClass находится в дереве наследования BaseClass, который определяет Prop5. Таким образом, доступ осуществляется благодаря части protected.

Ответ 3

Объединив защищенные и внутренние ключевые слова, член класса может быть помечен защищенным внутренним - только производные типы или типы в пределах одной сборки могут получить доступ к этому члену.

Эта статья MSDN отвечает на все ваши вопросы.

Ответ 5

В принципе, похоже, что это не так.

Смотрите - http://msdn.microsoft.com/en-us/library/ba0a1yw2(VS.80).aspx

защищенные внутренние действия как OR - доступ ограничивается производными классами или текущей сборкой.

Ответ 6

Защищенное ключевое слово - модификатор доступа к членству. Защищенный член доступен из класса, в котором он объявлен, и из любого класса, производного от класса, объявившего этот элемент.

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

Объединив защищенные и внутренние ключевые слова, член класса может быть помечен защищенным внутренним - только производные типы или типы в пределах одной сборки могут получить доступ к этому члену.

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

Ответ 7

Protected означает, что он разделяется только с классами потомков, только private означает, что он не может быть доступен кем-либо еще.

Изменить: комментарий Ханса делает ваш вопрос немного более ясным. Когда вы объединяете подобные модификаторы, они объединяются включительно не исключительно. Он доступен во всех путях internal или Protected.

Ответ 8

Поздний ответ, но я попался по той же проблеме. В конечном итоге я придумал частичное решение.

    internal Int MyInt
    {
        get;
        protected set;
    }

Он все еще отображается внутри сборки, но по крайней мере только классы наследования могут реально изменить его. Этого достаточно для того, чего я хотел.