Внутреннее защищенное свойство, доступное из другой сборки
Я создаю демо-код для начального сеанса по доступности, и я обнаружил, что я могу получить доступ к внутреннему защищенному свойству из производного класса. Что мне не хватает?
Сборка 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 отвечает на все ваши вопросы.
Ответ 4
Он выглядит как защищенные внутренние средства защищенный или внутренний.
Ответ 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;
}
Он все еще отображается внутри сборки, но по крайней мере только классы наследования могут реально изменить его. Этого достаточно для того, чего я хотел.