构造函数链接和空引用测试

时间:2011-06-03 14:50:44

标签: .net vb.net oop exception-handling constructor

如何在调用其他构造函数之前测试空值?

说:

  ' class MyHoyr '
  Public Sub New(ByVal myHour As MyHour)
    ' Can't doing it here !!!! '
    If myHour Is Nothing Then Throw New ArgumentNullException("myHour")

    ' Constructor call should be first '
    Me.New(myHour._timeSpan)

    ' Here is too late... '
  End Sub


  Private Sub New(ByVal timeSpan As TimeSpan)
    '.... '
  End Sub

4 个答案:

答案 0 :(得分:3)

我在C#中这样做的方法是在管道中使用静态方法,例如:

public MyHour(MyHour myHour) : this(GetTimeSpan(myHour))
{}

private static TimeSpan GetTimeSpan(MyHour myHour)
{
    if(myHour== null) throw new ArgumentNullException("myHour");
    return myHour._timeSpan;
}

private MyHour(TimeSpan timeSpan)
{...}

假设你可以在VB中做一些非常相似的事情。 (共享方法?)

Reflector向我保证这会转化为:

Public Sub New(ByVal myHour As MyHour)
    Me.New(MyHour.GetTimeSpan(myHour))
End Sub

Private Sub New(ByVal timeSpan As TimeSpan)
End Sub

Private Shared Function GetTimeSpan(ByVal myHour As MyHour) As TimeSpan
    If (myHourIs Nothing) Then
        Throw New ArgumentNullException("myHour")
    End If
    Return myHour._timeSpan
End Function

答案 1 :(得分:2)

丑陋的解决方法是一种扩展方法:

<Extension(), DebuggerNonUserCode()> _
Public Function EnsureNotNull(Of T As Class)(ByVal Value As T, _
                                             ByVal Arg As String) As T
    If Value Is Nothing Then Throw New ArgumentNullException(Arg)
    Return Value
End Function

用过:

' class MyHour '
Public Sub New(ByVal myHour As MyHour)
    Me.New(myHour.EnsureNotNull("myHour")._timeSpan)

End Sub

答案 2 :(得分:2)

处理此问题的一种简单方法是使用“命名构造函数”的概念,即工厂方法。

Public Shared Function Create (ByValue myHour As MyHour) As Foo
  If myHour Is Nothing Then Throw New ArgumentNullException("myHour")
  Return New Foo(myHour._timeSpan)
End Function

Private Sub New(ByVal timeSpan As TimeSpan)
  '.... '
End Sub

您可以看到System.Drawing.Color.FromArgb的类似示例,它们使用工厂方法来避免歧义。

答案 3 :(得分:0)

我最初的冲动是建议你甚至没有接受MyHour实例的构造函数。相反,让用户在课堂外检查Nothing:

Public Function GetSomeClassInstance(ByVal mh As MyHour) As SomeClass

    If mh IsNot Nothing Then
        Return New SomeClass(mh.TimeSpan)
    Else
        Throw New ArgumentNullException("mh", "MyHour instance must not be Nothing)
    End If

End Function

但是,使用私有构造函数来实际构造对象(如下所示)可能有效(未经测试):

Public Class SomeClass
    Public Sub New(ByVal mh As MyHour)
        MyClass.New(Nothing, mh)
    End Sub

    Public Sub New(ByVal ts As TimeSpan)
        MyClass.New(ts, Nothing)
    End Sub

    Private Sub New(ByVal ts As TimeSpan?, ByVal mh As MyHour)
        Dim _timeSpanToUse As TimeSpan

        If ts IsNot Nothing Then
            _timeSpanToUse = ts.Value
        Else
            If mh IsNot Nothing Then
                _timeSpanToUse = mh.TimeSpan
            Else
                Throw New ArgumentNullException("mh", "The MyHour parameter was NULL")
            End If
        End If

        'Continue using _timeSpanToUse here...
    End Sub
End Class