In Visual studio, is it possible (and how), to make VB.net compiler handles the use of a withevents field as a byref argument in a method call?

混江龙づ霸主 提交于 2019-12-13 03:39:58

问题


Title says it all...

Please read this full compiling sample code :

Imports System.Runtime.CompilerServices
Imports System.ComponentModel
Imports System.Drawing

Public Class PropertyChangedNotifier
    Implements INotifyPropertyChanged

    Protected Sub SetProperty(Of T)(ByRef _backingStoreField As T, ByVal new_value As T, <CallerMemberName> Optional ByVal propertyname As String = "")
        ' PropertyChangedNotifier allow me to add functionality here like 
        ' PropertyChanging with old and new value
        ' Locked current object is property IsReadOnly is true etc ...
        ' Save Old Original values
        ' etc

        ' Let's keep it simple for example
        _backingStoreField = new_value
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyname))
    End Sub

    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
End Class

Public Class VehicleEngine
    Public Property OilWarningAlert As Boolean
    Public Event OilWarningAlertChanged As EventHandler
    ' [...]
End Class

Public Interface IBulbReadOnly
    ReadOnly Property State As Boolean
End Interface

' just a light bulb on car dashboard
Public Class Bulb
    Implements IBulbReadOnly

    Public Property State As Boolean 'true => On, false => Off
    Public Sub New(color As Color)
    End Sub

    Public ReadOnly Property StateAsReadOnly As Boolean Implements IBulbReadOnly.State
        Get
            Return State
        End Get
    End Property
End Class

Public Class Car
    ' this base class has methods to handle changed & chagnging event, dirty state etc
    ' It implements INotifyPropertyChanged
    Inherits PropertyChangedNotifier

    Public Property Engine() As VehicleEngine
        Get
            Return _Engine
        End Get
        Set(ByVal value As VehicleEngine)
            SetProperty(_Engine, value)
            ' The line above compile fine but actually the generated code is 
            ' Dim tempEngine = _Engine
            ' SetProperty(tempEngine, value)
            ' _Engine = tempEngine
            ' So when SetProperty raise event the value is not changed in current car instance
        End Set
    End Property
    Private WithEvents _Engine As VehicleEngine

    Public ReadOnly Property OilWarningBulb As IBulbReadOnly
        Get
            Return _OilWarningBulb
        End Get
    End Property
    Private _OilWarningBulb As Bulb = New Bulb(Color.Red) ' display warning to driver

    Private Sub Engine_OilWarningChanged(ByVal sender As Object, ByVal e As EventArgs) Handles _Engine.OilWarningAlertChanged
        'When we change engine, we synchronize all other Car composites objects
        _OilWarningBulb.State = Engine.OilWarningAlert
    End Sub

    Private Sub OnPropertyChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs) Handles Me.PropertyChanged
        If (e.PropertyName = "Engine") Then
            Engine_OilWarningChanged() ' Synchronize the new engine with the car objects
        End If
    End Sub
    ' [...]
End Class


Module Test
    Sub Main()

        Dim car As Car = New Car()

        Dim bad_engine = New VehicleEngine()
        bad_engine.OilWarningAlert = True

        car.Engine = bad_engine
    End Sub
End Module

At first sight, this code seems fine for non expert VB.net developpers But it actually throws a NullReferenceException when settings car.Engine !

I do understand why this happens. This is because the line :

SetProperty(_Engine, value)

is actually handled by vb compiler as this block of code :

Dim tempEngine = _Engine
SetProperty(tempEngine, value)
_Engine = tempEngine

So when SetProperty raise event the current car object has still the old Engine ... (which is null/Nothing)

I dont like non explicit code So i would like to prevent compiler to generate temporary field like that... And make it consider field declared with withevents ineligible to be used as byref argument in a method call. This is, in my opinion, the behavior the compiler should have to have.

Do you know any way to do that ?

来源:https://stackoverflow.com/questions/24632610/in-visual-studio-is-it-possible-and-how-to-make-vb-net-compiler-handles-the

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!