Protected members and Generics craziness.


At last year’s TechEd Nick Randolph and I were discussing various aspects of generics. Nick pointed out to me a section in the language specification, which just didn’t seem right, so we tested it and it wasn’t. For some strange reason as I was archiving some files the other day I remembered there was an issue there, but couldn’t think what it was.. something to do with generics, Nick told me it was something to do with protected members. Putting those two together, here’s the issue(s)..

 

Astute readers of the VB language specification may have already stumbled onto the following part of section 4.6

 

For a generic type, the declaration context includes type parameters. This means that a generic type with one set of type arguments does not have access to the Private or Protected members of the generic type with a different set of type arguments. For example:
Class C(Of T)
   Private x As T
   Protected y As T
 
   Sub F()
       Dim z As C(Of String)
       ‘ Error: C(Of T) cannot access C(Of String)’s private members
       z.x = “a”
    End Sub Sub
End Class
Annotation
The C# language (and possibly other languages) allows a generic type to access Private and Protected members regardless of what type arguments are supplied. This should be kept in mind when designing generic classes that contain Protected members.
 

However, that isn’t actually the “accurate” story.

 

First, the code in the example does NOT produce an error. That is, within the class you can indeed access the private members across different constructed types.

 

However, you cannot access protected members in *derived* classes.

 

First let’s look at how VB works with protected members without generics.

 

Class c
    Protected a As String
End Class
 
Class d
    Inherits c
 
    Shared Sub foo()
          Dim x As New d
          x.a = “hello”
     End Sub
End Class

 

The above code works fine. Even from a Shared method you can access the protected member.  Now let’s change c and d to be generic.

 

 

Class c(Of T)
     Protected a As String
End Class
 
Class d(Of T)
    Inherits c(Of T)
 
    Shared Sub foo()
         Dim x As New d
         x.a = “hello”  ‘COMPILE ERROR
     End Sub
End Class

 

Now the above code won’t compile as VB won’t let you access the protected member.

 

To summarize:

 

Section 4.6 of the VB language specification is incorrect. You can access private members of a different constructed generic type.   You cannot access protected members of a different constructed generic type.

Personally I think this is a shame. It’s purely arbitrary on the part of the VB compiler.  The CLR and the C# compiler do allow you to access protected members.

 

That being said, it’s rare this will bite you, but when it does, unfortunately there probably is no recourse :(

 

 
This entry was posted in 491, 493. Bookmark the permalink.

One Response to Protected members and Generics craziness.

  1. Damn. I found this bug when I reviewed one of the beta versions of the language spec, but was too busy to do anything about it at the time – and then I couldn’t bloody remember what it was. I guess if I hadn’t remembered it, we wouldn’t be in this mess (at least, the doco would be right, if not the current behaviour :(

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>