4

I have read that a protected member can be accessed from derived classes, but the following does not work.

class A
{
    protected int Test;
}
class B:A
{
    A instanceOfA= new A()

    public B()
    {
        instanceOfA.Test //Not possible
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Miria
  • 469
  • 1
  • 5
  • 12
  • check out this answer - http://stackoverflow.com/questions/1836175/c-protected-members-accessed-via-base-class-variable/1836932#1836932 – yellowblood Apr 12 '11 at 15:51

7 Answers7

25

I have read that a protected member can be accessed from derived classes. Why my does my use of “protected” not work?

This is illegal because you have not provided a guarantee that you are accessing data of an instance of "B". Consider this similar case:

abstract class BankAccount
{
    protected int accountNumber;
}
class SwissBankAccount : BankAccount
{
}
--- in another assembly, evil-doers write ---
class EvilBankAccount : BankAccount
{
    void DoEvil()
    {
        BankAccount b = GetASwissBankAccount();
        int number = b.accountNumber;
    }
}

EvilBankAccount does not inherit from SwissBankAccount, so SwissBankAccount's protected member is not allowed to be used inside EvilBankAccount. You're allowed to access the protected members of your "parents", but not your "siblings"! EvilBankAccount can only access protected members of EvilBankAccount (or a type derived from EvilBankAccount). SwissBankAccount's protected members are off-limits.

The rule is that the type of the "receiver" expression that the protected instance member is accessed through has to be at least as derived as the type declaration containing the member access. For the precise wording of the rule and some illustrative examples see section 3.5.3 of the C# 4.0 specification.

Incidentally, C++ also has this rule.

This rule is frequently misunderstood. For a more in-depth analysis of this rule and some of the other consequences of protected access, see my articles on the subject. The most germane articles I've written on this subject are this one and this one. There are a bunch more articles I've written on related topics here (though some of them wander off the topic of protected access itself and onto the topic of how to use protected access to build a data model with parent references.)

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 9
    @FreeAsInBeer: Well, you are entitled to your expert opinion. I don't think your answer actually answered the question. Rather than answering "why does this use of protected not work?" as I did, you instead chose to say "you're doing it wrong" without ever explaining what rule of C# causes the error. I get this question frequently; it is a subtle point of language design and type safety. – Eric Lippert Apr 12 '11 at 16:16
  • 5
    @FreeAsInBeer: you **do know** who Eric Lippert is, right?? – marc_s Apr 12 '11 at 16:25
  • 9
    @marc_s: Though I take your point -- and it is thoroughly amusing that someone who was in third grade when I was first answering questions like this about programming language design is attempting to school me -- let's remember that StackOverflow is a community-based system. Answers are judged by the community based on their perceived correctness and usefulness, not on the alleged credentials of the person giving the answer. If young master Beer thinks I've given a crap answer, he's certainly entitled to his opinion and we shouldn't deny him that. – Eric Lippert Apr 12 '11 at 16:29
  • Since no one else has yet, I upvoted this answer. Yes, it's a bit more complicated than the asker might have been expecting, but that's because she asked a question that was a bit more complicated than she understood. It's worth it to read through a couple of times until you understand. Having other, simpler answers available is great, too. That's why multiple people are allowed to post answers. – Cody Gray - on strike Apr 12 '11 at 16:36
  • 1
    @Eric Lippert: sure - great community that SO is, too! I just guess with your position (as a member of the C# design team at Microsoft), you probably **do** have a tad more insights into the internals of how certains things in C# work than **most** other programmers out there :-) – marc_s Apr 12 '11 at 17:26
  • 7
    @FreeAsInBeer: My sincere advice is to take a deep breath and not be so emotionally involved. This is a community site and we're all here to help out and learn from each other by helping each other solve technical problems. Programming well is hard, languages are complex, and sarcasm doesn't help anyone. – Eric Lippert Apr 12 '11 at 17:50
3

You haven't set up your code correctly. Class B shouldn't have an instance of class A. Instead class B itself inherits the protected variables from class A.

Your code should look more like:

class A
{
   protected int Test;
}
class B:A
{
   public B()
   {
       int someInt = this.Test;
   }
}
FreeAsInBeer
  • 12,937
  • 5
  • 50
  • 82
  • +1 Just to add - You can access a base classes protected members from an instance of a derived class - see this for more detail http://msdn.microsoft.com/en-us/library/bcd5672a%28v=VS.71%29.aspx – tom502 Apr 12 '11 at 15:50
  • The thing is that I expected that I am allowed to access the protected members of base class instances so I just tried to create an instance of base class in derived class – Miria Apr 12 '11 at 15:51
  • @Miria: No, because you were simply creating a reference to class `A`. Even though the reference was in a derived class, access is still restricted as though it were a private variable because you were not accessing the variable through the derived class itself (`this.Test`). – FreeAsInBeer Apr 12 '11 at 15:55
  • @FreeAsInBeer: Well I was confused, I thought I can access to actual protected fields of instance of class that is base class. I thought it was like a public field but just for derived classes. So I was wrong – Miria Apr 12 '11 at 15:57
  • Let me tell you why I would down vote your answer. You changed the original question's code completely. Original code had a member of type A in type B, you changed it to make type B inherit from type A, just so that you can access the protected member. Why are you assuming that user wants to change the inheritance hierarchy and get rid of their member 'instanceOfA'? – SolutionYogi Apr 12 '11 at 17:44
  • 1
    @SolutionYogi - B inherits from A in the OP's code too. – Greg Apr 12 '11 at 17:48
  • 1
    @FreeAsInBeer: Really, seriously guy, take a deep breath. You're getting all het up about "truth" and "justice", but none of us are going to end up in The Hague (I hope). The simple fact is that this answer isn't very good. It doesn't even begin to address the actual question asked; remember, a "why" question should be answered with a "because" answer; you gave a "how to" answer appropriate to a "how do I" question. Take it as a learning opportunity; next time, read the question carefully and understand what question is really being asked. – Eric Lippert Apr 12 '11 at 18:01
  • @FreeAsInBeer - On the bright side, you still gained 50 rep from your answer. Remeber there are plenty of other questions in the sea. – Greg Apr 12 '11 at 18:02
  • 2
    @Eric, @Greg: Thanks. I appreciate the constructive criticism and hope to provide more clear answers that better address the question in the future. – FreeAsInBeer Apr 12 '11 at 18:06
  • Greg, that's what I get when I rush in to type a comment. You are right. My mistake. But I still feel that removing the member 'instanceOfA' is a BIG code change. – SolutionYogi Apr 12 '11 at 18:17
2

You can access the Test int within the B class itself. However, you cannot access properties of an instance. A does not know that it is a child of B so won't give access to its property.

class A
{
    protected int Test;
}
class B : A
{
    public B()
    {
       Test = 3; //possible
       base.Test = 3;  //explicitly calling base member, but not necessary in this case
    }
}
David Neale
  • 16,498
  • 6
  • 59
  • 85
2

Subclasses can access their own inherited members that are marked as protected.

class A
{
   protected int Test;
}

class B : A
{
   public B()
   {
     this.Test = 42; // Possible
   }
}
Greg
  • 23,155
  • 11
  • 57
  • 79
2

As B already inherits from A, you don't need a separate instance of A.

   public B()
   {
     this.Test = 1; //possible
   }
Town
  • 14,706
  • 3
  • 48
  • 72
2

You can access to it through the same class not as a public member of the base class.

class A 
{ 
    protected int Test; 
} 

class B:A 
{ 
    void TestMethod()
    {
         this.Test = 3; // Possible
    }
}

Check protected access modifier in C#.

Homam
  • 23,263
  • 32
  • 111
  • 187
2

You do not need to create an instance of A if you inherit A.

class A
{
   protected int Test;
}
class B:A
{
   public B()
   {
     this.Test = 666;
   }
}
John Hartsock
  • 85,422
  • 23
  • 131
  • 146