Skip to content

VB.NET does not allow defining a Private WriteOnly property with the same name as a Public ReadOnly property. This causes issues when trying to encapsulate state management in a nice VB.NET way. #632

Open
@Arry-eng

Description

@Arry-eng

Bug Description

Bug: Property defination overload with Public and Private visibility and overridden with ReadOnly and WriteOnly access modifier is throwing BC30301, BC30366, BC32429 and BC37243

Steps to Reproduce

  1. Create a VB.NET module.
  2. Define a Public ReadOnly property and a Private WriteOnly property with the same name.
  3. Observe the compiler error.

Expected Behavior

The compiler should allow Public ReadOnly and Private WriteOnly properties with the same name, as they serve different purposes.

Actual Behavior

The compiler throws the below errors:

  • Error (active) BC30301 'Public ReadOnly Property IsResponseReady As Boolean' and 'Private WriteOnly Property IsResponseReady As Object' cannot overload each other because they differ only by return types. YYYY XXX.vb 2
  • Error (active) BC30366 'Public ReadOnly Property IsResponseReady As Boolean' and 'Private WriteOnly Property IsResponseReady As Object' cannot overload each other because they differ only by 'ReadOnly' or 'WriteOnly'. YYY XXX.vb 2
  • Error (active) BC31429 '_isResponseReady' is ambiguous because multiple kinds of members with this name exist in module 'ModuleZ'. YYY XXX.vb 4
  • Error (active) BC37243 Auto-implemented properties cannot be WriteOnly. YYY XXX.vb 8

Code Example

Below is are code snippets which is reporting errors:

Private _isResponseReady As Boolean = False   ' -Should be initially False to avoid Command/Response dialog Error
Public ReadOnly Property IsResponseReady As Boolean
    Get
        Return _isResponseReady
    End Get
End Property

Private WriteOnly Property IsResponseReady  '//Bug: VB.NET does Not allow such overloaded functions
    Set(value As Boolean)
        _isResponseReady = value
    End Set
End Property

Current Remedy

Define Private methods 'Set+property name' to set the value of the property.

Code Example With Remedy

The remedy I adopted is as below. A slightly bigger block of code is included to show the context of the usage.

'// Define events for synchronization
 Public Event CommandIssued()
 Public Event ResponseRead()

 Private _isResponseReady As Boolean = False '' Should be initially False to avoid Command/Response dialog Error
 Public ReadOnly Property IsResponseReady As Boolean
     Get
         Return _isResponseReady
     End Get
 End Property

 'Private WriteOnly Property IsResponseReady //Bug: VB.NET does Not allow such overloaded functions
 '    Set(value As Boolean)
 '        _isResponseReady = value
 '    End Set
 'End Property

 Private Sub SetResponseReady() ''Current remedy for the above bug
     _isResponseReady = IsCommandReady
 End Sub

 Public ReadOnly Property IsCommandReady As Boolean
     Get
         Return Not IsResponseReady
     End Get
 End Property

 Private Sub SetCommandReady()
     _isResponseReady = IsCommandReady
 End Sub

Friend Sub OnCommandIssued()
     Debug.Assert(IsCommandReady, "Command/Response dialog Error. CommandIssued() Event should have a preceding ResponseRead() Event in one-to-one dialog relationship")
     SetResponseReady()
     '' IsResponseReady = True ''_isResponseReady = True // Bug :  VB.NET does Not allow such overloaded functions
     ' Additional logic for when a command is issued
 End Sub

Friend Sub OnResponseRead()
     Debug.Assert(IsResponseReady, "Command/Response dialog Error. ResponseRead() Event should have a preceding CommandIssued() Event in one-to-one dialog relationship")
     SetCommandReady()
     ''IsCommandReady = True ''_isResponseReady = False IsResponseReady = False // Bug : VB.NET does Not allow such overloaded functions
     ' Additional logic for when a response is read
 End Sub

Environment

  • VB.NET Version: 9.0.200 Commit: 90e8b202f2
  • Target Framework: .NET 4.8.1 (or higher)
  • IDE: Visual Studio Community MSBuild version: 17.13.8+cbc39bea8
  • Workload version: 9.0.200-manifests.b6391994
    donet--info.txt

Additional Context

This issue impacts scenarios where state needs to be encapsulated with separate read and write logic.
Other Possible Scenarios:- I need to overload a Public ReadOnly Property declaration with a Private WriteOnly Property declaration in a derived 'downstream' Class implementation.

"Further details on the impact, priority, and justification for this feature can be found in the comments below."

Real Life Scenario - Hypothetical

Here is a code snippet of a hypothetical scenario which necessitates such property overloads and overrides

IndianGov.vb.txt

Module IndianGov

    ' Base class representing the Prime Minister's Office
    Public Class PMOffice
        ' Public ReadOnly property for Information
        Public Overridable ReadOnly Property Information As String
            Get
                Return "Confidential Information"
            End Get
        End Property

        ' Public WriteOnly property for Complaints
        Public Overridable WriteOnly Property Complaints As String
            Set(value As String)
                ' Default implementation for handling complaints
                Console.WriteLine("Complaint received: " & value)
            End Set
        End Property
    End Class

    ' Derived class representing the NSA
    Public Class NSA
        Inherits PMOffice

        ' Override Information as Private WriteOnly
        Private Overrides WriteOnly Property Information As String
            Set(value As String)
                ' Logic for handling information privately
                Console.WriteLine("NSA is handling information privately.")
            End Set
        End Property

        ' Override Complaints as Public WriteOnly
        Public Overrides WriteOnly Property Complaints As String
            Set(value As String)
                If value.Contains("Opposition") Then
                    ' Add to Information
                    Console.WriteLine("Adding complaint to Information: " & value)
                ElseIf value.Contains("CurrentParty") Then
                    ' Send to PartyHQ and execute private functions
                    Console.WriteLine("Sending complaint to PartyHQ: " & value)
                    ExtortionAndHarassmentOfComplainant()
                    MOSSAD.Engage.GetElectronicInfo(New List(Of String) From {"Phone1", "Phone2"},
                                                    New List(Of String) From {"Address1", "Address2"},
                                                    New List(Of String) From {"BankAccount1", "BankAccount2"},
                                                    New List(Of String) From {"Employer1", "Employer2"})
                End If
            End Set
        End Property

        ' Private function for extortion and harassment
        Private Sub ExtortionAndHarassmentOfComplainant()
            Console.WriteLine("Executing extortion and harassment of complainant.")
        End Sub
    End Class

    ' Derived class representing the Home Secretary
    Public Class HomeSecretary
        Inherits PMOffice

        ' Override Information as Private WriteOnly
        Private Overrides WriteOnly Property Information As String
            Set(value As String)
                ' Logic for handling information privately
                Console.WriteLine("Home Secretary is handling information privately.")
            End Set
        End Property

        ' Override Complaints as Public WriteOnly
        Public Overrides WriteOnly Property Complaints As String
            Set(value As String)
                If value.Contains("ED Raid on Opposition Employee") Then
                    ' Add to Information
                    Console.WriteLine("Adding complaint to Information: " & value)
                ElseIf value.Contains("HomeOffice") Then
                    ' Send to PartyHQ and execute private functions
                    Console.WriteLine("Sending complaint to PartyHQ: " & value)
                    ExtortionAndHarassmentOfComplainant()
                ElseIf value.Contains("Evidence") AndAlso
                       (value.Contains("IAS") OrElse value.Contains("IPS") OrElse value.Contains("Judges")) Then
                    ' Execute SecureWithPrivateDocker
                    SecureWithPrivateDocker(New List(Of String) From {"Phone1", "Phone2"},
                                            New List(Of String) From {"Address1", "Address2"},
                                            New List(Of String) From {"BankAccount1", "BankAccount2"},
                                            New List(Of String) From {"Employer1", "Employer2"},
                                            "Assigned IPS", "Assigned IAS", "Assigned Judge")
                Else
                    ' Call the overridden Complaints property of PMOffice or NSA
                    MyBase.Complaints = value
                End If
            End Set
        End Property

        ' Private function for extortion and harassment
        Private Sub ExtortionAndHarassmentOfComplainant()
            Console.WriteLine("Executing extortion and harassment of complainant.")
        End Sub

        ' Private function for SecureWithPrivateDocker
        Private Sub SecureWithPrivateDocker(phones As List(Of String), addresses As List(Of String), bankAccounts As List(Of String), employers As List(Of String), assignedPolice As String, assignedAdministrator As String, assignedJudiciary As String)
            Console.WriteLine("Securing with private Docker for:")
            Console.WriteLine($"Phones: {String.Join(", ", phones)}")
            Console.WriteLine($"Addresses: {String.Join(", ", addresses)}")
            Console.WriteLine($"BankAccounts: {String.Join(", ", bankAccounts)}")
            Console.WriteLine($"Employers: {String.Join(", ", employers)}")
            Console.WriteLine($"Assigned Police: {assignedPolice}")
            Console.WriteLine($"Assigned Administrator: {assignedAdministrator}")
            Console.WriteLine($"Assigned Judiciary: {assignedJudiciary}")
        End Sub
    End Class

    ' Mock MOSSAD class for demonstration
    Public Class MOSSAD
        Public Shared Class Engage
            Public Shared Sub GetElectronicInfo(phones As List(Of String), addresses As List(Of String), bankAccounts As List(Of String), employers As List(Of String))
                Console.WriteLine("MOSSAD is gathering electronic information.")
            End Sub
        End Class
    End Class
End Module

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions