Posts Protected Overridable properties in NotInheritable classes in VB.NET
Post
Cancel

Protected Overridable properties in NotInheritable classes in VB.NET

I noticed that Jason posted up some code that we were discussion regarding some weirdness in some code I was converting from C# to VB.NET.  For the specifics of the problem, check out his blog.  After the fact, Paul Vick confirmed that it was indeed a bug (both to Jason and I via email) and will be fixed in VB 2K5.  However, until then, I found a couple of workarounds.

Workaround #1 (credit Paul Vick)

Remove the derived classes NotInheritable access modifier.  Although this would allow someone to inherit from your derived class, it's probably the safest workaround if you don't have access to the base class implementation or if your properties are read/write.  For some reason, this one didn't even enter into my head since I was focused on trying to keep the access levels the same between the VB and C# implementations.

Workaround #2:

Change the base class implementation from a ReadOnly Property to a Function of the same name.

<FONT color=#0000ff>Protected Overridable Function IntegerData() </FONT><FONT color=#0000ff>As Integer
  Return
42
<FONT color=#0000ff>End Function
</FONT></FONT>

And in the derived class:

<FONT color=#0000ff>Protected Overrides Function IntegerData() </FONT><FONT color=#0000ff>As Integer
  Return
44
<FONT color=#0000ff>End Property
</FONT></FONT>

The second workaround is great if you have access to the base class' source and you are replacing a readonly property.  If you don't, you can use workaround #1.

Workaround #3:

Change the Protected Overrides property in the derived class to be a Private Shadows property.

<FONT color=#0000ff>Private Shadows ReadOnly Property IntegerData()</FONT><FONT face="Courier New" color=#0000ff size=2> As Integer
</FONT><FONT color=#0000ff>  Get
    Return
44
</FONT><FONT face="Courier New" color=#0000ff size=2>  End Get
End Property</FONT>

[update] However, this workaround is not recommended.  Although it will give you a similar access level as Protected Overrides and removes the error, the access levels are not identical.  “If you were to cast an instance of the derived class to the base class, all of a sudden you'd be calling the base implementation again which is not the intent.“ (Paul Vick)  I didn't even think of that.  I suppose you could get away with this as long as you understand the implications and make sure your coding takes those into account.  I had to mention it since it's one of the things I found that appeared to be a solution in my experimentation.

The issue is related to the fact that a NotInheritable class can't have Protected members/methods; since Protected defines that the current and derived classes has access to those signatures.  There is a check in the compiler that will allow an exception the rule.  If it's an overridden signature, it allows those to be marked as Protected (since the signatures must match the base class signatures); however only for methods, not properties; and there's the bug.

Workaround #2 is what I ended up using in the strongly-typed ArrayList template I'm doing in CodeSmith; which as a property, even in the original C# code, FxCop barks since properties shouldn't return arrays.  So moving it to a function removes that message as well.  Another point concerning shadowing, FxCop seems to bark at you for anything that is shadowed. 

This post is licensed under CC BY 4.0 by the author.