views:

225

answers:

2

We have an interface, which can be grossly simplified as:

public interface IPersistable<T>
{
    T Id { get; }
}

Most places that implement the interface want to have it so that there is a protected or private set on that property, i.e, in C#:

public class Foo : IPersistable<int>
{
    public int Id { get; protected set; }
}

However, I can't get any sample VB.Net code to compile that follows the same pattern, whilst still implementing the interface, so:

Public Class Foo
    Implements IPersistable(Of Integer)

    Public Property Id() As Integer Implements IPersistable(Of Integer).Id
        Get
            Throw New NotImplementedException()
        End Get
        Protected Set(ByVal value As Integer)
            Throw New NotImplementedException()
        End Set
    End Property
End Class

...will not compile, but this would:

Public Class Foo
    Public Property Id() As Integer
        Get
            Throw New NotImplementedException()
        End Get
        Protected Set(ByVal value As Integer)
            Throw New NotImplementedException()
        End Set
    End Property
End Class

I appreciate that this example is overly trivial, and would possibly be better achieved through protected constructors, but I'm interested if it can be done in this manner?

[ EDIT: ] ...and obviously, if a type wants to use XMLSerialization, then the properties would need to be public read/write or the types would require custom serializers written for each.

Essentially, I see it that the interface should define the minimum accessibility, but VB is interpreting it as the exact accessibility?

+3  A: 

Yes, you'll have to implement the interface literally. A possible workaround is to republish the property in the class with another name:

Public Class Foo
  Implements IPersistable(Of Integer)
  Private m_Id As Integer

  Public ReadOnly Property Id() As Integer Implements IPersistable(Of Integer).Id
    Get
      Return m_Id
    End Get
  End Property

  Protected Property IdInternal() As Integer
    Get
      Return m_Id
    End Get
    Set(ByVal value As Integer)
      m_Id = value
    End Set
  End Property
End Class

Declare the property Overridable if you intend to override it in derived classes.

Hans Passant
+1 VBNET doesn't allow such change of modifier in the property getter and setter. You need to either republish the setter to another property, or have access to your private field which, of course, will have a different modifier than private. This is because the interface demands to be implemented as it's written. So, if you mark your Id property as public, not mentioning it a ReadOnly, you will have to make both Get and Set Public.
Will Marcouiller
Accepted, as I've now found this is a wishlist item: http://stackoverflow.com/questions/2362381/protected-set-in-vb-net-for-a-property-defined-in-an-interface/2365193#2365193
Rowland Shaw
A: 

It's not currently supported by the language, nor will it in Visual Basic 10 (i.e. the version with Visual Studio 2010). There is a wishlist item for exactly this. Until then, workarounds such as that suggested by nobugz are the only option.

Rowland Shaw