Доступ к защищенным членам C# через переменную базового класса
Это может показаться довольно новым вопросом, но можете ли вы объяснить, почему метод Der.B() не может получить доступ к защищенному Foo через переменную базового класса? Это выглядит странно для меня:
public class Base
{
protected int Foo;
}
public class Der : Base
{
private void B(Base b) { Foo = b.Foo; } // Error: Cannot access protected member
private void D(Der d) { Foo = d.Foo; } // OK
}
Спасибо!
5 ответов
Это часто задаваемый вопрос. Чтобы понять, почему это незаконно, подумайте, что может пойти не так.
Предположим, у вас есть еще один производный класс Frob, производный от Base. Теперь вы передаете экземпляр Frob Der.B. Должны ли вы иметь доступ к Frob.Foo из Der.B? Нет, абсолютно нет. Frob.Foo защищен; он должен быть доступен только из Frob и его подклассов. Der не является Frob и не является подклассом Frob, поэтому он не получает доступ к защищенным членам Frob.
Если это не ясно, см. Мою статью на эту тему:
http://blogs.msdn.com/ericlippert/archive/2005/11/09/491031.aspx
В B вы пытаетесь получить доступ к защищенному члену другого класса. Тот факт, что вы наследуете от этого класса, не имеет значения. В D вы получаете доступ к защищенному члену базового класса вашего текущего класса. В этом контексте вы можете получить доступ к чему угодно из Der и к защищенным членам типа, от которого она наследуется.
Вы можете обойти это ограничение, объявив статический метод в базовом классе:
public class Base
{
protected int Foo;
protected static int GetFoo(Base b)
{
return b.Foo;
}
}
public class Der : Base
{
private void B(Base b) { Foo = GetFoo(b); } // OK
}
Проще говоря, защищенный позволяет доступ к подклассам.
В:
private void B(Base b) { Foo = b.Foo; }
Вы пытаетесь получить доступ к защищенному члену, к которому у вашего экземпляра Der нет доступа. У него был бы доступ только к нему, если бы это был базовый класс вашего текущего экземпляра Der (this).
private void D(Der d) { Foo = d.Foo; } // OK
Работает нормально, потому что вы проходите через Der для доступа к защищенному методу базовых классов.
В сценарии, который вы пытаетесь использовать, вы захотите использовать "внутреннее" для int Foo.