C# protected members accessed via base class variable

10,837

Solution 1

This is a frequently asked question. To figure out why this is illegal, think about what could go wrong.

Suppose you had another derived class Frob derived from Base. Now you pass an instance of Frob to Der.B. Should you be able to access Frob.Foo from Der.B? No, absolutely not. Frob.Foo is protected; it should only be accessible from Frob and subclasses of Frob. Der is not Frob and is not a subclass of Frob, so it does not get access to Frob's protected members.

If that's not clear, see my article on the subject:

http://blogs.msdn.com/ericlippert/archive/2005/11/09/491031.aspx

Solution 2

In B you are trying to access a protected member of another class. The fact that you are inheriting from that class is irrelevant. In D you are accessing a protected member of the base class of your current class. In this context you can access anything from Der and the protected members of the type it is inheriting from.

Solution 3

You can work around this limitation by declaring a static method in the base class:

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
}

Solution 4

Simply put, protected allows access to sub classes.

In:

private void B(Base b) { Foo = b.Foo; }

You are attempting to access a protected member your instance of Der doesn't have access to. It would only have access to it if it was the base class of your current instance of Der (this).

private void D(Der d) { Foo = d.Foo; } // OK

Works fine because you are going through Der to access it's Base classes protected method.

Share:
10,837
Roman
Author by

Roman

programmer

Updated on June 03, 2022

Comments

  • Roman
    Roman almost 2 years

    It may seems rather newbie question, but can you explain why method Der.B() cannot access protected Foo via Base class variable? This looks weird to me:

    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
    }
    

    Thanks!

  • Yuriy Faktorovich
    Yuriy Faktorovich over 14 years
    This will not work if B is passed a Base not a Der.
  • Roman
    Roman over 14 years
    I know that I can use internal or even public instead of protected. But I want to understand why protected behaves like described in the post.
  • Yuriy Faktorovich
    Yuriy Faktorovich over 14 years
    @Roman: Because protected is only visible to the Derived class. Inside the same instance. But you are trying to look at it from a different instance. If that could be done, protected would be pretty much useless.
  • Jay Riggs
    Jay Riggs over 14 years
    @Roman - RagePotato answers that.
  • Doug
    Doug over 14 years
    I think you meant to say: private void D(Der d) { Foo = d.Foo; } Works fine. A little confusing b/c you duplicated the line of code.
  • Roman
    Roman over 14 years
    +1 for explanation, but I still doubt why "the fact that you are inheriting from that class is irrelevant"? Is it spec predicate?
  • Yuriy Faktorovich
    Yuriy Faktorovich over 14 years
    The fact that you are inheriting from it gives you access to it if someone initializes a Der. In which case you could cast it to Der and then access Foo.
  • Ben Lesh
    Ben Lesh over 14 years
    Yuriy is correct. The code I posted was garbage. lol. I removed it. Eric Lippert's answer is correct, furthermore, I have to wonder why you would want to do this and not make it internal?
  • Ragepotato
    Ragepotato over 14 years
    Woops, yeah I meant to copy the second code sample.
  • Roman
    Roman over 14 years
    Thank you. Its clear to me now.