Есть ли способ получить "защищенный" член другого объекта из производного типа? - PullRequest
12 голосов
/ 05 декабря 2008
class MyBase
{
    protected object PropertyOfBase { get; set; }
}

class MyType : MyBase
{
    void MyMethod(MyBase parameter)
    {
        // I am looking for:
        object p = parameter.PropertyOfBase;  // error CS1540: Cannot access protected member 'MyBase.PropertyOfBase' via a qualifier of type 'MyBase'; the qualifier must be of type 'MyType' (or derived from it)
    }
}

Есть ли способ получить защищенное свойство параметра типа из расширяющего типа без отражения? Поскольку расширяющий класс знает о свойстве через его базовый тип, это имело бы смысл, если это возможно.

Ответы [ 7 ]

16 голосов
/ 14 июня 2012

В прошлый раз, когда я сталкивался с подобной проблемой, я использовал решение добавления защищенного статического метода к базе:

class MyBase
{
    protected object PropertyOfBase { get; set; }

    protected static object GetPropertyOfBaseOf(MyBase obj) 
    {
        return obj.PropertyOfBase;
    }
}

class MyType : MyBase
{
    void MyMethod(MyBase parameter)
    {
        object p = GetPropertyOfBaseOf(parameter);
    }
}
11 голосов
/ 05 декабря 2008

Нет, вы не можете этого сделать.

Вам разрешен доступ только к защищенным членам объектов типа доступа (или производных от него). Здесь мы не знаем, имеет ли параметр тип MyType или SomeOtherCompletelyDifferentType.

EDIT: соответствующий бит спецификации C # 3.0 - раздел 3.5.3:

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

5 голосов
/ 05 декабря 2008

Есть веская причина, по которой ты не можешь этого сделать. Предположим, кто-то пишет:

class Other : MyBase { }

new MyType().MyMethod(new Other());

Если язык разрешил то, что вы просите, вы можете нарушить предполагаемые инварианты Other, изменив значение PropertyOfBase.

2 голосов
/ 05 декабря 2008

Я думаю, вы должны спросить себя, есть ли лучший способ сделать то, что вы хотите сделать. Вы хотите, чтобы PropertyOfBase действовал как общедоступный в контексте MyType.MyMethod (), но был защищен во всех других ситуациях. Почему?

1 голос
/ 05 декабря 2008

Защищенное свойство доступно только экземпляру производного класса, но не экземплярам производных классов.

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

(Отредактировано, я немного привязал язык!)

0 голосов
/ 06 марта 2018

Вы также можете объявить MyType как вложенный класс MyBase (вместо наследования), таким образом, вы можете получить доступ к закрытым / защищенным членам, когда отправляете класс MyBase в качестве параметра

public class MyBase
{
    protected object PropertyOfBase { get; set; }

    public class MyType
    {
        public void MyMethod(MyBase parameter)
        {
            object p = parameter.PropertyOfBase;  
        }
    }
}

Для создания экземпляра MyType просто используйте

var t = new MyBase.MyType();
t.MyMethod(new MyBase());
0 голосов
/ 02 марта 2018

Поскольку вы наследуете от MyBase, вы можете получить доступ ко всем полям / свойствам / методам из него, помеченным как «защищенные», с помощью ключевого слова «base».

public class MyBase
{
    protected object PropertyOfBase { get; set; }
}

public class MyType : MyBase
{
    void MyMethod()
    {
        object p =  base.PropertyOfBase;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...